diff --git a/ilspy_dump/ror2_csproj/AkGameObjUtil.cs b/ilspy_dump/ror2_csproj/AkGameObjUtil.cs new file mode 100644 index 0000000..ca5f3e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/AkGameObjUtil.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public static class AkGameObjUtil +{ + public static void SetAkGameObjectStatic(GameObject gameObj, bool staticSetting) + { + if (gameObj.TryGetComponent(out var component)) + { + component.isStaticAfterDelay = staticSetting; + } + } +} diff --git a/ilspy_dump/ror2_csproj/AlternateButtonEvents.cs b/ilspy_dump/ror2_csproj/AlternateButtonEvents.cs new file mode 100644 index 0000000..d6b639b --- /dev/null +++ b/ilspy_dump/ror2_csproj/AlternateButtonEvents.cs @@ -0,0 +1,27 @@ +using RoR2.UI; +using UnityEngine; +using UnityEngine.Events; + +[RequireComponent(typeof(HGButton))] +public class AlternateButtonEvents : MonoBehaviour +{ + public UnityEvent onAlternateClick; + + public UnityEvent onTertiaryClick; + + public void InvokeAltClick() + { + if (onAlternateClick != null) + { + onAlternateClick.Invoke(); + } + } + + public void InvokeTertiaryClick() + { + if (onTertiaryClick != null) + { + onTertiaryClick.Invoke(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/ApplicationDataStruct.cs b/ilspy_dump/ror2_csproj/ApplicationDataStruct.cs new file mode 100644 index 0000000..8b4eed9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ApplicationDataStruct.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; + +[Serializable] +internal class ApplicationDataStruct +{ + public uint quickPlayCutoffTime; + + public string hostName = ""; + + public int Serialize(byte[] destinationBuf) + { + int offset = 0; + EncodeUint(quickPlayCutoffTime, ref offset, ref destinationBuf); + EncodeString(hostName, ref offset, ref destinationBuf); + return offset; + } + + private void EncodeUint(uint u, ref int offset, ref byte[] destinationBuf) + { + BitConverter.GetBytes(u).CopyTo(destinationBuf, offset); + offset += 4; + } + + private void EncodeString(string s, ref int offset, ref byte[] destinationBuf) + { + byte[] bytes = Encoding.ASCII.GetBytes(s); + byte[] bytes2 = BitConverter.GetBytes(bytes.Length); + bytes2.CopyTo(destinationBuf, offset); + offset += bytes2.Length; + bytes.CopyTo(destinationBuf, offset); + offset += bytes.Length; + } + + public void Deserialize(byte[] buffer, uint dataSize) + { + int offset = 0; + quickPlayCutoffTime = DecodeUint(ref offset, buffer); + hostName = DecodeString(ref offset, buffer); + } + + private uint DecodeUint(ref int offset, byte[] buffer) + { + uint result = BitConverter.ToUInt32(buffer, offset); + offset += 4; + return result; + } + + private string DecodeString(ref int offset, byte[] buffer) + { + string result = null; + int num = BitConverter.ToInt32(buffer, offset); + offset += 4; + if (num > 0) + { + result = Encoding.ASCII.GetString(buffer, offset, num); + offset += num; + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform.PS5/OnScreenLog.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform.PS5/OnScreenLog.cs new file mode 100644 index 0000000..a8e2e68 --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform.PS5/OnScreenLog.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +namespace Assets.RoR2.Scripts.Platform.PS5; + +public class OnScreenLog : MonoBehaviour +{ +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/ActivityData.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/ActivityData.cs new file mode 100644 index 0000000..6c57e5d --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/ActivityData.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Assets.RoR2.Scripts.Platform; + +[CreateAssetMenu(menuName = "RoR2/ActivityData")] +public class ActivityData : ScriptableObject +{ + [SerializeField] + private List activities; + + public BaseActivity LookupActivityByID(string activityID) + { + foreach (BaseActivity activity in activities) + { + if (activity.ActivityID == activityID) + { + return activity; + } + } + return null; + } + + public List CompareActivityCriteria(BaseActivitySelector activitySelector) + { + List list = new List(); + foreach (BaseActivity activity in activities) + { + if (activitySelector.IsCompatibleWith(activity)) + { + list.Add(activity); + } + } + return list; + } +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/ActivityManager.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/ActivityManager.cs new file mode 100644 index 0000000..62ade5b --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/ActivityManager.cs @@ -0,0 +1,384 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RoR2; +using RoR2.EntitlementManagement; +using RoR2.UI.MainMenu; +using UnityEngine; +using UnityEngine.AddressableAssets; +using UnityEngine.ResourceManagement.AsyncOperations; + +namespace Assets.RoR2.Scripts.Platform; + +public class ActivityManager +{ + protected ActivityData LoadedActivityData; + + protected Dictionary InProgressActivities = new Dictionary(); + + protected Dictionary AvailableActivities = new Dictionary(); + + protected BaseActivity ActivityToProcess; + + public bool IsInitialized { get; private set; } + + public BaseActivity.ActivityGameMode CurrentGameMode + { + get + { + GameModeIndex gameModeIndex = GameModeIndex.Invalid; + if (null != PreGameController.instance) + { + gameModeIndex = PreGameController.instance.gameModeIndex; + } + if (null != Run.instance) + { + gameModeIndex = Run.instance.gameModeIndex; + } + if (GameModeIndex.Invalid != gameModeIndex) + { + if (gameModeIndex == GameModeCatalog.FindGameModeIndex("ClassicRun")) + { + return BaseActivity.ActivityGameMode.ClassicRun; + } + if (gameModeIndex == GameModeCatalog.FindGameModeIndex("EclipseRun")) + { + return BaseActivity.ActivityGameMode.Eclipse; + } + if (gameModeIndex == GameModeCatalog.FindGameModeIndex("InfiniteTowerRun")) + { + return BaseActivity.ActivityGameMode.InfiniteTower; + } + if (gameModeIndex == GameModeCatalog.FindGameModeIndex("WeeklyRun")) + { + return BaseActivity.ActivityGameMode.WeeklyRun; + } + } + Debug.LogError("ActivityManager::CurrentGameMode property unable to determine GameMode."); + return BaseActivity.ActivityGameMode.Any; + } + } + + public BaseActivity.ActivityGameType CurrentGameType + { + get + { + ReadOnlyCollection readOnlyLocalPlayersList = NetworkUser.readOnlyLocalPlayersList; + if (readOnlyLocalPlayersList != null) + { + if (readOnlyLocalPlayersList.Count == 1) + { + return BaseActivity.ActivityGameType.SinglePlayer; + } + if (readOnlyLocalPlayersList.Count > 1) + { + return BaseActivity.ActivityGameType.MultiPlayer; + } + } + Debug.LogError("ActivityManager::CurrentGameType property unable to determine GameType."); + return BaseActivity.ActivityGameType.Any; + } + } + + public BaseActivity.ActivitySurvivor CurrentSurvivor + { + get + { + UserProfile userProfile = LocalUserManager.GetFirstLocalUser()?.userProfile; + if (userProfile != null) + { + SurvivorDef survivorDef = userProfile?.GetSurvivorPreference(); + if (null != survivorDef) + { + BaseActivity.ActivitySurvivor result = BaseActivity.ActivitySurvivor.Any; + if (Enum.TryParse(survivorDef.cachedName, out result)) + { + return result; + } + } + } + Debug.LogError("ActivityManager::CurrentSurvivor property unable to determine survivor."); + return BaseActivity.ActivitySurvivor.Any; + } + } + + private bool ValidCurrentSelectorExists + { + get + { + if ((null != PreGameController.instance || null != Run.instance) && LocalUserManager.GetFirstLocalUser()?.userProfile != null) + { + if (NetworkUser.readOnlyLocalPlayersList != null) + { + return NetworkUser.readOnlyLocalPlayersList.Count >= 0; + } + return false; + } + return false; + } + } + + public BaseActivitySelector CurrentActivitySelector + { + get + { + if (ValidCurrentSelectorExists) + { + return new BaseActivitySelector + { + activitySurvivor = CurrentSurvivor, + activityGameMode = CurrentGameMode, + activityGameType = CurrentGameType + }; + } + return null; + } + } + + public virtual void Initialize() + { + MainMenuController.OnPreMainMenuInitialized -= OnPreMainMenuInitializedCallback; + MainMenuController.OnPreMainMenuInitialized += OnPreMainMenuInitializedCallback; + LocalUserManager.onUserSignIn -= OnLocalUserSignIn; + LocalUserManager.onUserSignIn += OnLocalUserSignIn; + BaseUserEntitlementTracker.OnAllUserEntitlementsUpdated = (Action)Delegate.Remove(BaseUserEntitlementTracker.OnAllUserEntitlementsUpdated, new Action(OnEntitlementsChangedCallback)); + BaseUserEntitlementTracker.OnAllUserEntitlementsUpdated = (Action)Delegate.Combine(BaseUserEntitlementTracker.OnAllUserEntitlementsUpdated, new Action(OnEntitlementsChangedCallback)); + Run.onRunStartGlobal += OnRunStartGlobal; + Run.onClientGameOverGlobal += OnClientGameOverGlobal; + } + + protected virtual void OnPreMainMenuReInitializedCallback() + { + AbandonInProgressActivities(); + } + + protected virtual void OnLocalUserSignIn(LocalUser localUser) + { + if (localUser.userProfile != null && localUser.userProfile == LocalUserManager.GetFirstLocalUser().userProfile) + { + RebuildActivityAvailabilityForUser(localUser); + IsInitialized = true; + } + } + + protected virtual void AbandonInProgressActivities() + { + BaseActivitySelector activitySelector = new BaseActivitySelector(); + PlatformSystems.activityManager.TryToAbandonActivity(activitySelector); + } + + protected virtual void OnClientGameOverGlobal(Run run, RunReport runReport) + { + if (runReport.gameEnding == RoR2Content.GameEndings.StandardLoss) + { + if (ValidCurrentSelectorExists) + { + PlatformSystems.activityManager.TryToFailActivity(PlatformSystems.activityManager.CurrentActivitySelector); + } + else + { + Debug.LogError("ActivityManager::OnClientGameOverGlobal - missing context to fail activities activities on Game Over."); + } + } + } + + protected virtual void OnRunStartGlobal(Run run) + { + if (ValidCurrentSelectorExists) + { + TryToStartActivity(CurrentActivitySelector); + } + else + { + Debug.LogError("ActivityManager::OnRunStartGlobal - missing context to start activities on Run start."); + } + } + + protected virtual void OnPreMainMenuInitializedCallback() + { + MainMenuController.OnPreMainMenuInitialized -= OnPreMainMenuInitializedCallback; + AsyncOperationHandle handle = Addressables.LoadAssetAsync("RoR2/Base/Common/ActivityData.asset"); + ActivityData loadedActivityData = handle.WaitForCompletion(); + LoadedActivityData = loadedActivityData; + Addressables.Release(handle); + if (GameIntentReceiver.GameIntentAdapter.hasPendingGameIntent) + { + CreateStartupActivity(); + } + GameIntentReceiver.GameIntentAdapter.OnGameIntentReceivedEvent -= GameIntentReceiverListener; + GameIntentReceiver.GameIntentAdapter.OnGameIntentReceivedEvent += GameIntentReceiverListener; + if (ActivityToProcess != null) + { + RoR2Application.instance.StartCoroutine(ProcessGameActivity()); + GameIntentReceiver.GameIntentAdapter.ClearPendingGameIntent(); + } + MainMenuController.OnPreMainMenuInitialized += OnPreMainMenuReInitializedCallback; + } + + protected virtual void CreateStartupActivity() + { + } + + public virtual void GameIntentReceiverListener(GameIntentAdapter.EventResponse eventResponseObject) + { + eventResponseObject.EventHasBeenHandled(eventHandled: false); + } + + public virtual void TryToStartActivity(BaseActivitySelector activitySelector) + { + } + + public virtual void TryToCompleteActivity(BaseActivitySelector activitySelector, bool markUnavailableOnComplete = true, bool applyAsDelta = true) + { + } + + public virtual void TryToAbandonActivity(BaseActivitySelector activitySelector) + { + } + + public virtual void TryToFailActivity(BaseActivitySelector activitySelector) + { + } + + public virtual void TryToSetActivityAvailability(BaseActivitySelector activitySelector, bool newAvailability, bool applyAsDelta = true, bool sendImmediate = true) + { + } + + public virtual void FlushAvailabilityUpdates(bool applyAsDelta) + { + } + + public virtual bool ShouldSkipGameIntentHandler(BaseActivity activity) + { + return CurrentActivitySelector?.IsCompatibleWith(activity) ?? false; + } + + public virtual bool IsActivityAvailable(BaseActivity baseActivity) + { + return AvailableActivities.ContainsKey(baseActivity.ActivityID); + } + + protected IEnumerator ProcessGameActivity() + { + if (!IsInitialized) + { + yield return new WaitForEndOfFrame(); + } + BaseActivity gameActivity = LoadedActivityData.LookupActivityByID(ActivityToProcess.ActivityID); + if (gameActivity == null) + { + Debug.LogError("ActivityManager::ProcessGameActivity() was unable to find data for a Game Activity!"); + yield break; + } + if (!IsActivityAvailable(gameActivity)) + { + Debug.LogError("ActivityManager::ProcessGameActivity() user attempted to launch an unavailable activity!"); + yield break; + } + if (!RoR2Application.IsMainScene) + { + if (ShouldSkipGameIntentHandler(gameActivity)) + { + yield break; + } + global::RoR2.Console.instance.SubmitCmd(null, "transition_command \"disconnect\";"); + yield return new WaitForSeconds(1f); + global::RoR2.Console.instance.SubmitCmd(null, "transition_command \"set_scene title\";"); + while (!RoR2Application.IsMainScene) + { + yield return new WaitForEndOfFrame(); + } + } + while (!RoR2Application.IsMainMenuInitialized) + { + yield return new WaitForEndOfFrame(); + } + string gameModeStr; + if (gameActivity.GameMode == BaseActivity.ActivityGameMode.ClassicRun || gameActivity.GameMode == BaseActivity.ActivityGameMode.Any) + { + gameModeStr = "ClassicRun"; + } + else if (gameActivity.GameMode == BaseActivity.ActivityGameMode.WeeklyRun) + { + gameModeStr = "WeeklyRun"; + } + else if (gameActivity.GameMode == BaseActivity.ActivityGameMode.Eclipse) + { + gameModeStr = "EclipseRun"; + } + else if (gameActivity.GameMode == BaseActivity.ActivityGameMode.InfiniteTower) + { + gameModeStr = "InfiniteTowerRun"; + } + else + { + Debug.LogError("ActivityManager::ProcessGameActivity() - Trying to transition to gamemode with unhandled BaseActivity.ActivityGameMode. Transitioning to Classic Run..."); + gameModeStr = "ClassicRun"; + } + while (TransitionCommand.requestPending) + { + yield return new WaitForEndOfFrame(); + } + global::RoR2.Console.instance.SubmitCmd(null, "transition_command \"gamemode " + gameModeStr + "; host 0;\""); + string text = gameActivity.Survivor.ToString(); + if (string.Compare("Any", text) != 0) + { + SurvivorIndex survivorIndex = SurvivorCatalog.FindSurvivorIndex(text); + UserProfile userProfile = LocalUserManager.GetFirstLocalUser()?.userProfile; + if (userProfile.HasSurvivorUnlocked(survivorIndex)) + { + SurvivorDef survivorDef = SurvivorCatalog.GetSurvivorDef(survivorIndex); + userProfile.SetSurvivorPreference(survivorDef); + } + } + yield return new WaitForSeconds(2f); + RoR2Application.SetMapsEnabled(enabled: true); + } + + public void RebuildActivityAvailabilityForUser(LocalUser localUser) + { + if (LoadedActivityData == null) + { + return; + } + UserProfile userProfile = localUser.userProfile; + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + List list = LoadedActivityData.CompareActivityCriteria(baseActivitySelector); + foreach (BaseActivity item in list) + { + if (item.AchievementID.Length == 0) + { + continue; + } + baseActivitySelector.activityAchievementID = item.AchievementID; + bool flag = userProfile.CanSeeAchievement(item.AchievementID); + bool flag2 = userProfile.HasAchievement(item.AchievementID); + if (item.RequiredEntitlementID.Length > 0) + { + if (EntitlementCatalog.FindEntitlementIndex(item.RequiredEntitlementID) == EntitlementIndex.None) + { + Debug.LogError("ActivityManager::RebuildAvailabilityForUser - Activity requires entitlement (" + item.RequiredEntitlementID + ") that is not defined in the EntitlementCatalog. (probably a typo)"); + } + else + { + EntitlementDef entitlementDef = EntitlementCatalog.GetEntitlementDef(EntitlementCatalog.FindEntitlementIndex(item.RequiredEntitlementID)); + if (!EntitlementManager.localUserEntitlementTracker.UserHasEntitlement(localUser, entitlementDef)) + { + flag = false; + } + } + } + TryToSetActivityAvailability(baseActivitySelector, flag && !flag2, applyAsDelta: false, sendImmediate: false); + } + if (list.Count > 0) + { + FlushAvailabilityUpdates(applyAsDelta: false); + } + } + + private void OnEntitlementsChangedCallback() + { + RebuildActivityAvailabilityForUser(LocalUserManager.GetFirstLocalUser()); + } +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/BaseActivity.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/BaseActivity.cs new file mode 100644 index 0000000..dbd9e3d --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/BaseActivity.cs @@ -0,0 +1,92 @@ +using System; +using UnityEngine; + +namespace Assets.RoR2.Scripts.Platform; + +[Serializable] +public class BaseActivity +{ + public enum ActivityGameType : uint + { + SinglePlayer, + MultiPlayer, + Any + } + + public enum ActivityGameMode : uint + { + ClassicRun, + Eclipse, + InfiniteTower, + WeeklyRun, + Any + } + + public enum ActivitySurvivor : uint + { + Bandit2, + Captain, + Commando, + Croco, + Engi, + Heretic, + Huntress, + Loader, + Mage, + Merc, + Toolbot, + Treebot, + Railgunner, + Any + } + + [SerializeField] + protected ActivityGameType _gameType; + + [SerializeField] + protected ActivityGameMode _gameMode; + + [SerializeField] + protected ActivitySurvivor _survivor; + + [SerializeField] + protected string _activityID; + + [SerializeField] + protected string _achievementID; + + [SerializeField] + protected string _requiredEntitlementID; + + public ActivityGameType GameType => _gameType; + + public ActivityGameMode GameMode => _gameMode; + + public ActivitySurvivor Survivor => _survivor; + + public string ActivityID => _activityID; + + public string AchievementID => _achievementID; + + public string RequiredEntitlementID => _requiredEntitlementID; + + public virtual void StartActivity() + { + Debug.LogError("BaseActivity::StartActivity() invoked!"); + } + + public virtual void CompleteActivity() + { + Debug.LogError("BaseActivity::CompleteActivity() invoked!"); + } + + public virtual void AbandonActivity() + { + Debug.LogError("BaseActivity::AbandonActivity() invoked!"); + } + + public virtual void FailActivity() + { + Debug.LogError("BaseActivity::FailActivity() invoked!"); + } +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/BaseActivitySelector.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/BaseActivitySelector.cs new file mode 100644 index 0000000..a8b1bda --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/BaseActivitySelector.cs @@ -0,0 +1,25 @@ +namespace Assets.RoR2.Scripts.Platform; + +public class BaseActivitySelector +{ + public BaseActivity.ActivityGameType activityGameType = BaseActivity.ActivityGameType.Any; + + public BaseActivity.ActivityGameMode activityGameMode = BaseActivity.ActivityGameMode.Any; + + public BaseActivity.ActivitySurvivor activitySurvivor = BaseActivity.ActivitySurvivor.Any; + + public string activityAchievementID = ""; + + public bool IsCompatibleWith(BaseActivity activity) + { + if ((activity.GameType == BaseActivity.ActivityGameType.Any || activityGameType == BaseActivity.ActivityGameType.Any || activity.GameType == activityGameType) && (activity.GameMode == BaseActivity.ActivityGameMode.Any || activityGameMode == BaseActivity.ActivityGameMode.Any || activity.GameMode == activityGameMode) && (activity.Survivor == BaseActivity.ActivitySurvivor.Any || activitySurvivor == BaseActivity.ActivitySurvivor.Any || activity.Survivor == activitySurvivor)) + { + if (activity.AchievementID.Length != 0 && activityAchievementID.Length != 0) + { + return activity.AchievementID.CompareTo(activityAchievementID) == 0; + } + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/GameIntentAdapter.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/GameIntentAdapter.cs new file mode 100644 index 0000000..ca8c6e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/GameIntentAdapter.cs @@ -0,0 +1,38 @@ +using System; + +namespace Assets.RoR2.Scripts.Platform; + +public class GameIntentAdapter +{ + public class EventResponse : EventArgs + { + public bool wasEventHandledByAnySystem { get; private set; } + + public void EventHasBeenHandled(bool eventHandled) + { + wasEventHandledByAnySystem |= eventHandled; + } + } + + public virtual bool hasPendingGameIntent => false; + + public event Action OnGameIntentReceivedEvent; + + public virtual void Initialize() + { + } + + public virtual void ClearPendingGameIntent() + { + } + + protected void FireGameIntentReceived() + { + EventResponse eventResponse = new EventResponse(); + this.OnGameIntentReceivedEvent?.Invoke(eventResponse); + if (eventResponse.wasEventHandledByAnySystem) + { + ClearPendingGameIntent(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/GameIntentReceiver.cs b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/GameIntentReceiver.cs new file mode 100644 index 0000000..c100db1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/Assets.RoR2.Scripts.Platform/GameIntentReceiver.cs @@ -0,0 +1,12 @@ +namespace Assets.RoR2.Scripts.Platform; + +public static class GameIntentReceiver +{ + public static GameIntentAdapter GameIntentAdapter { get; private set; } = new GameIntentAdapter(); + + + public static void Initialize() + { + GameIntentAdapter.Initialize(); + } +} diff --git a/ilspy_dump/ror2_csproj/AutomatedBuildVersion.cs b/ilspy_dump/ror2_csproj/AutomatedBuildVersion.cs new file mode 100644 index 0000000..76846c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/AutomatedBuildVersion.cs @@ -0,0 +1,4 @@ +public static class AutomatedBuildVersion +{ + public const string buildVersionString = "290"; +} diff --git a/ilspy_dump/ror2_csproj/BeamPointsFromTransforms.cs b/ilspy_dump/ror2_csproj/BeamPointsFromTransforms.cs new file mode 100644 index 0000000..45a9e2c --- /dev/null +++ b/ilspy_dump/ror2_csproj/BeamPointsFromTransforms.cs @@ -0,0 +1,41 @@ +using System; +using UnityEngine; + +[ExecuteAlways] +public class BeamPointsFromTransforms : MonoBehaviour +{ + [Tooltip("Line Renderer to set the positions of.")] + public LineRenderer target; + + [Tooltip("Transforms to use as the points for the line renderer.")] + [SerializeField] + private Transform[] pointTransforms = Array.Empty(); + + private void Start() + { + UpdateBeamPositions(); + } + + private void Update() + { + UpdateBeamPositions(); + } + + private void UpdateBeamPositions() + { + if (!target) + { + return; + } + int num = pointTransforms.Length; + target.positionCount = num; + for (int i = 0; i < num; i++) + { + Transform transform = pointTransforms[i]; + if ((bool)transform) + { + target.SetPosition(i, transform.position); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/BeginRapidlyActivatingAndDeactivating.cs b/ilspy_dump/ror2_csproj/BeginRapidlyActivatingAndDeactivating.cs new file mode 100644 index 0000000..460d35c --- /dev/null +++ b/ilspy_dump/ror2_csproj/BeginRapidlyActivatingAndDeactivating.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +public class BeginRapidlyActivatingAndDeactivating : MonoBehaviour +{ + public float blinkFrequency = 10f; + + public float delayBeforeBeginningBlinking = 30f; + + public GameObject blinkingRootObject; + + private float fixedAge; + + private float blinkAge; + + private void FixedUpdate() + { + fixedAge += Time.fixedDeltaTime; + if (fixedAge >= delayBeforeBeginningBlinking) + { + blinkAge += Time.fixedDeltaTime; + if (blinkAge >= 1f / blinkFrequency) + { + blinkAge -= 1f / blinkFrequency; + blinkingRootObject.SetActive(!blinkingRootObject.activeSelf); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/BezierCurveLine.cs b/ilspy_dump/ror2_csproj/BezierCurveLine.cs new file mode 100644 index 0000000..31b696d --- /dev/null +++ b/ilspy_dump/ror2_csproj/BezierCurveLine.cs @@ -0,0 +1,88 @@ +using System; +using UnityEngine; + +[RequireComponent(typeof(LineRenderer))] +[ExecuteAlways] +public class BezierCurveLine : MonoBehaviour +{ + private Vector3[] vertexList = Array.Empty(); + + private Vector3 p0 = Vector3.zero; + + public Vector3 v0 = Vector3.zero; + + public Vector3 p1 = Vector3.zero; + + public Vector3 v1 = Vector3.zero; + + public Transform endTransform; + + public bool animateBezierWind; + + public Vector3 windMagnitude; + + public Vector3 windFrequency; + + private Vector3 windPhaseShift; + + private Vector3 lastWind; + + private Vector3 finalv0; + + private Vector3 finalv1; + + private float windTime; + + public LineRenderer lineRenderer { get; private set; } + + private void Awake() + { + lineRenderer = GetComponent(); + windPhaseShift = UnityEngine.Random.insideUnitSphere * 360f; + Array.Resize(ref vertexList, lineRenderer.positionCount + 1); + UpdateBezier(0f); + } + + public void OnEnable() + { + Array.Resize(ref vertexList, lineRenderer.positionCount + 1); + } + + private void LateUpdate() + { + UpdateBezier(Time.deltaTime); + } + + public void UpdateBezier(float deltaTime) + { + windTime += deltaTime; + p0 = base.transform.position; + if ((bool)endTransform) + { + p1 = endTransform.position; + } + if (animateBezierWind) + { + finalv0 = v0 + new Vector3(Mathf.Sin(MathF.PI / 180f * (windTime * 360f + windPhaseShift.x) * windFrequency.x) * windMagnitude.x, Mathf.Sin(MathF.PI / 180f * (windTime * 360f + windPhaseShift.y) * windFrequency.y) * windMagnitude.y, Mathf.Sin(MathF.PI / 180f * (windTime * 360f + windPhaseShift.z) * windFrequency.z) * windMagnitude.z); + finalv1 = v1 + new Vector3(Mathf.Sin(MathF.PI / 180f * (windTime * 360f + windPhaseShift.x + p1.x) * windFrequency.x) * windMagnitude.x, Mathf.Sin(MathF.PI / 180f * (windTime * 360f + windPhaseShift.y + p1.z) * windFrequency.y) * windMagnitude.y, Mathf.Sin(MathF.PI / 180f * (windTime * 360f + windPhaseShift.z + p1.y) * windFrequency.z) * windMagnitude.z); + } + else + { + finalv0 = v0; + finalv1 = v1; + } + for (int i = 0; i < vertexList.Length; i++) + { + float t = (float)i / (float)(vertexList.Length - 2); + vertexList[i] = EvaluateBezier(t); + } + lineRenderer.SetPositions(vertexList); + } + + private Vector3 EvaluateBezier(float t) + { + Vector3 a = Vector3.Lerp(p0, p0 + finalv0, t); + Vector3 b = Vector3.Lerp(p1, p1 + finalv1, 1f - t); + return Vector3.Lerp(a, b, t); + } +} diff --git a/ilspy_dump/ror2_csproj/BlockObjectOnLoad.cs b/ilspy_dump/ror2_csproj/BlockObjectOnLoad.cs new file mode 100644 index 0000000..a9f325b --- /dev/null +++ b/ilspy_dump/ror2_csproj/BlockObjectOnLoad.cs @@ -0,0 +1,18 @@ +using System; +using RoR2; +using UnityEngine; + +public class BlockObjectOnLoad : MonoBehaviour +{ + private void Start() + { + if (!RoR2Application.loadFinished) + { + base.gameObject.SetActive(value: false); + RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate + { + base.gameObject.SetActive(value: true); + }); + } + } +} diff --git a/ilspy_dump/ror2_csproj/BobObject.cs b/ilspy_dump/ror2_csproj/BobObject.cs new file mode 100644 index 0000000..0e063b5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/BobObject.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +public class BobObject : MonoBehaviour +{ + public float bobDelay; + + public Vector3 bobDistance = Vector3.zero; + + private Vector3 initialPosition; + + private void Start() + { + if ((bool)base.transform.parent) + { + initialPosition = base.transform.localPosition; + } + else + { + initialPosition = base.transform.position; + } + } + + private void FixedUpdate() + { + if ((bool)Run.instance) + { + Vector3 vector = initialPosition + bobDistance * Mathf.Sin(Run.instance.fixedTime - bobDelay); + if ((bool)base.transform.parent) + { + base.transform.localPosition = vector; + } + else + { + base.transform.position = vector; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/ChefController.cs b/ilspy_dump/ror2_csproj/ChefController.cs new file mode 100644 index 0000000..5fff293 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ChefController.cs @@ -0,0 +1,528 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using EntityStates; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +public class ChefController : NetworkBehaviour +{ + public delegate void YesChefEnded(); + + [HideInInspector] + public SkillStateOverrideData skillOverrides; + + private bool localCleaverFired; + + [SyncVar] + public bool _cleaverAway; + + [SyncVar] + public bool _recallCleaver; + + [NonSerialized] + [SyncVar] + public bool catchDirtied; + + [NonSerialized] + public CleaverProjectile projectile; + + [NonSerialized] + public CharacterBody characterBody; + + public Animator chefAnimator; + + internal float spreadBloom; + + public bool rolyPolyActive; + + private bool yesChefHeatActive; + + public YesChefEnded yesChefEndedDelegate; + + public bool blockOtherSkills; + + private bool cleaversAwayCached; + + public Transform handCleaverBone; + + public Transform[] cleaverStockBones; + + private Vector3[] cleaverStockBones_DefaultLocalPosition; + + private float[] cleaverStockBones_AnimateInTimer01; + + private uint soundIDMoving; + + private uint soundIDServo; + + private float walkVolume_Target; + + private float walkVolume_Smoothed; + + private float servoStrain_Timer; + + private float servoStrain_VolumeSmoothed; + + private const float servoStrainFadeInDuration = 0.15f; + + private const float servoStrainFadeOutDuration = 0.5f; + + private Queue cachedCleaverProjectileInfo = new Queue(); + + private Dictionary cleaverDictionary = new Dictionary(); + + private static int kCmdCmdSetCleaverAway; + + private static int kCmdCmdSetRecallCleaver; + + public bool cleaverAway + { + get + { + if (!localCleaverFired) + { + return _cleaverAway; + } + return true; + } + set + { + if (base.hasAuthority) + { + Network_cleaverAway = value; + CallCmdSetCleaverAway(value); + } + } + } + + public bool recallCleaver + { + get + { + return _recallCleaver; + } + set + { + if (base.hasAuthority) + { + Network_recallCleaver = value; + CallCmdSetRecallCleaver(value); + } + } + } + + public bool Network_cleaverAway + { + get + { + return _cleaverAway; + } + [param: In] + set + { + SetSyncVar(value, ref _cleaverAway, 1u); + } + } + + public bool Network_recallCleaver + { + get + { + return _recallCleaver; + } + [param: In] + set + { + SetSyncVar(value, ref _recallCleaver, 2u); + } + } + + public bool NetworkcatchDirtied + { + get + { + return catchDirtied; + } + [param: In] + set + { + SetSyncVar(value, ref catchDirtied, 4u); + } + } + + [Command] + public void CmdSetCleaverAway(bool b) + { + Network_cleaverAway = b; + } + + [Command] + public void CmdSetRecallCleaver(bool b) + { + Network_recallCleaver = b; + } + + private void Awake() + { + int num = cleaverStockBones.Length; + cleaverStockBones_DefaultLocalPosition = new Vector3[num]; + cleaverStockBones_AnimateInTimer01 = new float[num]; + for (int i = 0; i < num; i++) + { + cleaverStockBones_DefaultLocalPosition[i] = cleaverStockBones[i].localPosition; + } + soundIDMoving = Util.PlaySound("Play_chef_move_loop", base.gameObject); + soundIDServo = Util.PlaySound("Play_chef_servo_loop", base.gameObject); + if (characterBody == null) + { + characterBody = GetComponent(); + } + chefAnimator = characterBody.modelLocator.modelTransform.GetComponent(); + } + + private void Start() + { + CharacterBody obj = characterBody; + obj.onJump = (CharacterBody.JumpDelegate)Delegate.Combine(obj.onJump, new CharacterBody.JumpDelegate(HandleJump)); + } + + private void OnDestroy() + { + CharacterBody obj = characterBody; + obj.onJump = (CharacterBody.JumpDelegate)Delegate.Remove(obj.onJump, new CharacterBody.JumpDelegate(HandleJump)); + } + + public void SetYesChefHeatState(bool newYesChefHeatState) + { + yesChefHeatActive = newYesChefHeatState; + if (!yesChefHeatActive) + { + yesChefEndedDelegate?.Invoke(); + } + } + + private void HandleJump() + { + ActivateServoStrainSfxForDuration(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ActivateServoStrainSfxForDuration(float duration = 0.5f) + { + servoStrain_Timer = Mathf.Max(servoStrain_Timer, duration); + } + + public void CacheCleaverProjectileFireInfo(FireProjectileInfo fireProjectileInfo) + { + cachedCleaverProjectileInfo.Enqueue(fireProjectileInfo); + } + + public bool TryRetrieveCachedProjectileFireInfo(out FireProjectileInfo fireProjectileInfo) + { + fireProjectileInfo = default(FireProjectileInfo); + if (cachedCleaverProjectileInfo.Count < 0 || !base.hasAuthority) + { + return false; + } + fireProjectileInfo = cachedCleaverProjectileInfo.Dequeue(); + return true; + } + + private void Update() + { + if ((bool)characterBody && !recallCleaver && cleaverAway) + { + characterBody.SetSpreadBloom(spreadBloom); + } + CharacterMotor characterMotor = characterBody.characterMotor; + Vector3 velocity = characterMotor.velocity; + float sqrMagnitude = velocity.sqrMagnitude; + bool isGrounded = characterMotor.isGrounded; + bool @bool = chefAnimator.GetBool("isSprinting"); + Vector3 vector = (characterBody.inputBank ? characterBody.inputBank.moveVector : Vector3.zero); + if (isGrounded && sqrMagnitude > Mathf.Epsilon) + { + if (rolyPolyActive) + { + walkVolume_Target = 1f; + } + else if (vector != Vector3.zero) + { + if (@bool) + { + walkVolume_Target = 0.8f; + } + else + { + walkVolume_Target = 0.5f; + } + } + } + else + { + walkVolume_Target = Mathf.MoveTowards(walkVolume_Target, 0f, Time.deltaTime / (1f / 3f)); + } + walkVolume_Smoothed = Mathf.MoveTowards(walkVolume_Smoothed, Mathf.Clamp01(walkVolume_Target), Time.deltaTime / (4f / 15f)); + AkSoundEngine.SetRTPCValueByPlayingID("charChefSpeed", walkVolume_Smoothed * 100f, soundIDMoving); + if (servoStrain_Timer > 0f) + { + servoStrain_Timer -= Time.deltaTime; + } + if (servoStrain_Timer > 0f) + { + float maxDelta = Time.deltaTime / 0.15f; + servoStrain_VolumeSmoothed = Mathf.MoveTowards(servoStrain_VolumeSmoothed, 1f, maxDelta); + } + else + { + float maxDelta2 = Time.deltaTime / 0.5f; + servoStrain_VolumeSmoothed = Mathf.MoveTowards(servoStrain_VolumeSmoothed, 0f, maxDelta2); + } + } + + private void LateUpdate() + { + bool flag = cleaverDictionary.Count > 0; + if (flag != cleaversAwayCached || flag) + { + cleaversAwayCached = flag; + handCleaverBone.localScale = (flag ? Vector3.zero : Vector3.one); + } + if (!(characterBody != null) || !(characterBody.skillLocator != null) || !(characterBody.skillLocator.primary != null)) + { + return; + } + int stock = characterBody.skillLocator.primary.stock; + int num = cleaverStockBones.Length; + float deltaTime = Time.deltaTime; + float num2 = 8f; + float num3 = -0.2f; + for (int i = 0; i < num; i++) + { + bool num4 = i + 1 <= stock; + float current = cleaverStockBones_AnimateInTimer01[i]; + current = ((!num4) ? 0f : Mathf.MoveTowards(current, 1f, deltaTime * num2)); + cleaverStockBones_AnimateInTimer01[i] = current; + if (current != 1f) + { + current = 1f - current; + current *= current; + cleaverStockBones[i].localScale = Vector3.one * (1f - current); + cleaverStockBones[i].localPosition = cleaverStockBones_DefaultLocalPosition[i] + current * Vector3.up * num3; + } + } + } + + internal void AddLocalProjectileReference(ushort predictionId, CleaverProjectile cleaverProjectile) + { + if (!cleaverDictionary.ContainsKey(predictionId) || !cleaverProjectile.projectileController.isPrediction) + { + cleaverDictionary[predictionId] = cleaverProjectile; + } + } + + internal void RemoveLocalProjectileReference(ushort predictionId) + { + if (cleaverDictionary.ContainsKey(predictionId)) + { + cleaverDictionary.Remove(predictionId); + } + if (cleaverDictionary.Count < 1) + { + localCleaverFired = false; + cleaverAway = false; + recallCleaver = false; + } + } + + public void TransferSkillOverrides(SkillStateOverrideData skillOverrideData) + { + if (skillOverrides != null) + { + if (skillOverrides == skillOverrideData) + { + return; + } + skillOverrides.ClearOverrides(); + } + skillOverrides = skillOverrideData; + } + + public void ClearSkillOverrides() + { + if (skillOverrides != null) + { + skillOverrides.ClearOverrides(); + } + skillOverrides = null; + } + + [Server] + public void DestroyCleavers() + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void ChefController::DestroyCleavers()' called on client"); + return; + } + foreach (CleaverProjectile value in cleaverDictionary.Values) + { + value.CallCmdDestroyAndCleanup(); + } + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdSetCleaverAway(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdSetCleaverAway called on client."); + } + else + { + ((ChefController)obj).CmdSetCleaverAway(reader.ReadBoolean()); + } + } + + protected static void InvokeCmdCmdSetRecallCleaver(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdSetRecallCleaver called on client."); + } + else + { + ((ChefController)obj).CmdSetRecallCleaver(reader.ReadBoolean()); + } + } + + public void CallCmdSetCleaverAway(bool b) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdSetCleaverAway called on server."); + return; + } + if (base.isServer) + { + CmdSetCleaverAway(b); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdSetCleaverAway); + networkWriter.Write(GetComponent().netId); + networkWriter.Write(b); + SendCommandInternal(networkWriter, 0, "CmdSetCleaverAway"); + } + + public void CallCmdSetRecallCleaver(bool b) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdSetRecallCleaver called on server."); + return; + } + if (base.isServer) + { + CmdSetRecallCleaver(b); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdSetRecallCleaver); + networkWriter.Write(GetComponent().netId); + networkWriter.Write(b); + SendCommandInternal(networkWriter, 0, "CmdSetRecallCleaver"); + } + + static ChefController() + { + kCmdCmdSetCleaverAway = -1756854004; + NetworkBehaviour.RegisterCommandDelegate(typeof(ChefController), kCmdCmdSetCleaverAway, InvokeCmdCmdSetCleaverAway); + kCmdCmdSetRecallCleaver = 535604397; + NetworkBehaviour.RegisterCommandDelegate(typeof(ChefController), kCmdCmdSetRecallCleaver, InvokeCmdCmdSetRecallCleaver); + NetworkCRC.RegisterBehaviour("ChefController", 0); + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(_cleaverAway); + writer.Write(_recallCleaver); + writer.Write(catchDirtied); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(_cleaverAway); + } + if ((base.syncVarDirtyBits & 2u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(_recallCleaver); + } + if ((base.syncVarDirtyBits & 4u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(catchDirtied); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + _cleaverAway = reader.ReadBoolean(); + _recallCleaver = reader.ReadBoolean(); + catchDirtied = reader.ReadBoolean(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + _cleaverAway = reader.ReadBoolean(); + } + if (((uint)num & 2u) != 0) + { + _recallCleaver = reader.ReadBoolean(); + } + if (((uint)num & 4u) != 0) + { + catchDirtied = reader.ReadBoolean(); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/ChefFoodPickController.cs b/ilspy_dump/ror2_csproj/ChefFoodPickController.cs new file mode 100644 index 0000000..e5afbd5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ChefFoodPickController.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class ChefFoodPickController : MonoBehaviour +{ + [SerializeField] + public GameObject foodModel1; + + [SerializeField] + public GameObject foodModel2; + + [SerializeField] + public GameObject foodModel3; + + private void Start() + { + switch (Random.Range(0, 2)) + { + case 0: + foodModel1.SetActive(value: true); + break; + case 1: + foodModel2.SetActive(value: true); + break; + case 2: + foodModel3.SetActive(value: true); + break; + } + } +} diff --git a/ilspy_dump/ror2_csproj/ChildLocator.cs b/ilspy_dump/ror2_csproj/ChildLocator.cs new file mode 100644 index 0000000..bc550ac --- /dev/null +++ b/ilspy_dump/ror2_csproj/ChildLocator.cs @@ -0,0 +1,96 @@ +using System; +using UnityEngine; + +[DisallowMultipleComponent] +public class ChildLocator : MonoBehaviour +{ + [Serializable] + private struct NameTransformPair + { + public string name; + + public Transform transform; + } + + [SerializeField] + private NameTransformPair[] transformPairs = Array.Empty(); + + public int Count => transformPairs.Length; + + public int FindChildIndex(string childName) + { + for (int i = 0; i < transformPairs.Length; i++) + { + if (childName == transformPairs[i].name) + { + return i; + } + } + return -1; + } + + public int FindChildIndex(Transform childTransform) + { + for (int i = 0; i < transformPairs.Length; i++) + { + if ((object)childTransform == transformPairs[i].transform) + { + return i; + } + } + return -1; + } + + public string FindChildName(int childIndex) + { + if ((uint)childIndex < transformPairs.Length) + { + return transformPairs[childIndex].name; + } + return null; + } + + public Transform FindChild(string childName) + { + return FindChild(FindChildIndex(childName)); + } + + public GameObject FindChildGameObject(int childIndex) + { + Transform transform = FindChild(childIndex); + if (!transform) + { + return null; + } + return transform.gameObject; + } + + public GameObject FindChildGameObject(string childName) + { + return FindChildGameObject(FindChildIndex(childName)); + } + + public Transform FindChild(int childIndex) + { + if ((uint)childIndex < transformPairs.Length) + { + return transformPairs[childIndex].transform; + } + return null; + } + + public T FindChildComponent(string childName) + { + return FindChildComponent(FindChildIndex(childName)); + } + + public T FindChildComponent(int childIndex) + { + Transform transform = FindChild(childIndex); + if (!transform) + { + return default(T); + } + return transform.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/ConditionalLOD.cs b/ilspy_dump/ror2_csproj/ConditionalLOD.cs new file mode 100644 index 0000000..874401c --- /dev/null +++ b/ilspy_dump/ror2_csproj/ConditionalLOD.cs @@ -0,0 +1,119 @@ +using UnityEngine; + +public class ConditionalLOD : MonoBehaviour +{ + public int PS4lod = -1; + + public int XBoxlod = -1; + + public int Switchlod = 1; + + public int SwitchHandHeldlod = 2; + + public int Defaultlod = -1; + + public int maxlod; + + private LODGroup lg; + + private void Start() + { + } + + private void OnEnable() + { + GetRenderers(); + int lODState = GetLODState(); + SetState(lODState); + } + + public int GetLODPercentage(LOD[] lods, int i) + { + if (i == 0) + { + return 100; + } + return (int)(lods[i - 1].screenRelativeTransitionHeight * 100f + 0.5f); + } + + private void ResetLOD() + { + GetRenderers(); + } + + private void GetRenderers() + { + lg = GetComponent(); + LOD[] lODs = lg.GetLODs(); + int num = -1; + for (int i = 0; i < lODs.Length; i++) + { + if (lODs[i].renderers != null && lODs[i].renderers.Length != 0) + { + num = i; + } + } + maxlod = num; + } + + public int GetLODState() + { + return Defaultlod; + } + + private void SetState(int lodState) + { + LOD[] lODs = lg.GetLODs(); + if (lodState == -1) + { + lg.enabled = true; + for (int i = 0; i < lODs.Length; i++) + { + Renderer[] renderers = lODs[i].renderers; + for (int j = 0; j < renderers.Length; j++) + { + renderers[j].gameObject.SetActive(value: true); + } + } + return; + } + for (int k = 0; k < lODs.Length; k++) + { + Renderer[] renderers = lODs[k].renderers; + for (int j = 0; j < renderers.Length; j++) + { + renderers[j].gameObject.SetActive(value: false); + } + } + lodState = Mathf.Min(lodState, maxlod); + int num = maxlod - lodState + 1; + if (num == 1 || !Application.isPlaying) + { + lg.enabled = false; + Renderer[] renderers = lODs[lodState].renderers; + for (int j = 0; j < renderers.Length; j++) + { + renderers[j].gameObject.SetActive(value: true); + } + return; + } + lg.enabled = true; + int num2 = 0; + LOD[] array = new LOD[num]; + for (int l = lodState; l < lODs.Length; l++) + { + Renderer[] renderers = lODs[l].renderers; + for (int j = 0; j < renderers.Length; j++) + { + renderers[j].gameObject.SetActive(value: true); + } + array[num2] = lODs[l]; + if (l + 1 < lODs.Length) + { + array[num2].screenRelativeTransitionHeight = lODs[num2].screenRelativeTransitionHeight; + } + num2++; + } + lg.SetLODs(array); + } +} diff --git a/ilspy_dump/ror2_csproj/ConditionalObject.cs b/ilspy_dump/ror2_csproj/ConditionalObject.cs new file mode 100644 index 0000000..f134dc9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ConditionalObject.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +[DefaultExecutionOrder(-5)] +public class ConditionalObject : MonoBehaviour +{ + public bool enabledOnSwitch = true; + + public bool enabledOnXbox = true; + + public bool enabledOnPlaystation = true; + + public bool disableInProduction; + + public bool enabledOnSteam = true; + + public bool enabledOnEGS = true; + + public bool disableIfNoActiveRun; + + private void CheckConditions() + { + bool flag = false || enabledOnEGS || enabledOnSteam; + base.gameObject.SetActive(flag && !disableInProduction); + } + + private void Awake() + { + CheckConditions(); + } +} diff --git a/ilspy_dump/ror2_csproj/CubicBezier3.cs b/ilspy_dump/ror2_csproj/CubicBezier3.cs new file mode 100644 index 0000000..f8bede7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/CubicBezier3.cs @@ -0,0 +1,67 @@ +using System; +using UnityEngine; + +[Serializable] +public struct CubicBezier3 +{ + public Vector3 a; + + public Vector3 b; + + public Vector3 c; + + public Vector3 d; + + public Vector3 p0 => a; + + public Vector3 p1 => d; + + public Vector3 v0 => b - a; + + public Vector3 v1 => c - d; + + public static CubicBezier3 FromVelocities(Vector3 p0, Vector3 v0, Vector3 p1, Vector3 v1) + { + CubicBezier3 result = default(CubicBezier3); + result.a = p0; + result.b = p0 + v0; + result.c = p1 + v1; + result.d = p1; + return result; + } + + public Vector3 Evaluate(float t) + { + float num = t * t; + float num2 = num * t; + return a + 3f * t * (b - a) + 3f * num * (c - 2f * b + a) + num2 * (d - 3f * c + 3f * b - a); + } + + public void ToVertices(Vector3[] results) + { + ToVertices(results, 0, results.Length); + } + + public void ToVertices(Vector3[] results, int spanStart, int spanLength) + { + float num = 1f / (float)(spanLength - 1); + for (int i = 0; i < spanLength; i++) + { + results[spanStart++] = Evaluate((float)i * num); + } + } + + public float ApproximateLength(int samples) + { + float num = 1f / (float)(samples - 1); + float num2 = 0f; + Vector3 vector = p0; + for (int i = 1; i < samples; i++) + { + Vector3 vector2 = Evaluate((float)i * num); + num2 += Vector3.Distance(vector, vector2); + vector = vector2; + } + return num2; + } +} diff --git a/ilspy_dump/ror2_csproj/DelusionPickerController.cs b/ilspy_dump/ror2_csproj/DelusionPickerController.cs new file mode 100644 index 0000000..5ffc8df --- /dev/null +++ b/ilspy_dump/ror2_csproj/DelusionPickerController.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class DelusionPickerController : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ilspy_dump/ror2_csproj/DestroyOnKill.cs b/ilspy_dump/ror2_csproj/DestroyOnKill.cs new file mode 100644 index 0000000..8bf7488 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DestroyOnKill.cs @@ -0,0 +1,13 @@ +using RoR2; +using UnityEngine; + +public class DestroyOnKill : MonoBehaviour, IOnKilledServerReceiver +{ + public GameObject effectPrefab; + + public void OnKilledServer(DamageReport damageReport) + { + Object.Instantiate(effectPrefab, base.transform.position, base.transform.rotation); + Object.Destroy(base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/DestroyOnParticleEnd.cs b/ilspy_dump/ror2_csproj/DestroyOnParticleEnd.cs new file mode 100644 index 0000000..dcca850 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DestroyOnParticleEnd.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +public class DestroyOnParticleEnd : MonoBehaviour +{ + [SerializeField] + [Tooltip("Set this if you want to specify which particle system is tracked. Otherwise it will automatically grab the first one it finds.")] + private ParticleSystem trackedParticleSystem; + + private EffectManagerHelper efh; + + public void Start() + { + if (trackedParticleSystem == null) + { + trackedParticleSystem = GetComponentInChildren(); + } + if (!efh) + { + efh = GetComponent(); + } + } + + public void Update() + { + if ((bool)trackedParticleSystem && !trackedParticleSystem.IsAlive()) + { + if ((bool)efh && efh.OwningPool != null) + { + efh.OwningPool.ReturnObject(efh); + } + else + { + Object.Destroy(base.gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/DestroyOnSoundEnd.cs b/ilspy_dump/ror2_csproj/DestroyOnSoundEnd.cs new file mode 100644 index 0000000..1744709 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DestroyOnSoundEnd.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +[RequireComponent(typeof(AudioSource))] +public class DestroyOnSoundEnd : MonoBehaviour +{ + private AudioSource audioSource; + + private void Awake() + { + audioSource = GetComponent(); + } + + private void Update() + { + if (!audioSource.isPlaying) + { + Object.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/DevCheatMenu.cs b/ilspy_dump/ror2_csproj/DevCheatMenu.cs new file mode 100644 index 0000000..c0de1ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/DevCheatMenu.cs @@ -0,0 +1,252 @@ +using System; +using System.Linq; +using System.Text; +using RoR2; +using RoR2.ContentManagement; +using RoR2.UI; +using TMPro; +using UnityEngine; + +[RequireComponent(typeof(MPEventSystemLocator))] +public class DevCheatMenu : MonoBehaviour +{ + public TextMeshProUGUI enemyName; + + public TextMeshProUGUI teamText; + + public TextMeshProUGUI affixText; + + public TextMeshProUGUI spawnEnemyText; + + public TextMeshProUGUI toggleSpawningText; + + public TextMeshProUGUI miscCommandLabel; + + public TMP_Dropdown masterNameDropdown; + + public TMP_Dropdown enemiesAmountDropdown; + + public TMP_Dropdown itemsNamesDropdown; + + public TMP_Dropdown itemsAmountDropdown; + + public TMP_Dropdown stageListDropdown; + + private string enemyMasterName; + + private string teamIndex; + + private string equipmentIndex; + + private string enemyMasterNameTeamIndexEquipmentIndex; + + private bool spawnEnemyArgsDirty; + + private readonly StringBuilder miscCommand = new StringBuilder(); + + private NetworkUser localUser; + + private MPEventSystem eventSystem; + + private bool isUpper; + + private void Awake() + { + Close(); + } + + private void SetMonsterTabText() + { + spawnEnemyText.SetText(enemyMasterNameTeamIndexEquipmentIndex); + enemyName.SetText(enemyMasterName); + teamText.SetText(teamIndex); + affixText.SetText(equipmentIndex); + toggleSpawningText.SetText(CombatDirector.cvDirectorCombatDisable.value ? "Spawning DISABLED" : "Spawning ENABLED"); + } + + private void InitializeMasterDropdown() + { + masterNameDropdown.options = MasterCatalog.allMasters.Select((CharacterMaster master) => new TMP_Dropdown.OptionData(master.gameObject.name)).ToList(); + } + + private void InitializeStageListDropdown() + { + stageListDropdown.options = SceneCatalog.allSceneDefs.Select((SceneDef scene) => new TMP_Dropdown.OptionData(scene.baseSceneName)).ToList(); + } + + public void EnableSpawning() + { + } + + public void DisableSpawning() + { + } + + public void SpawnEnemy() + { + if (!CombatDirector.cvDirectorCombatDisable.value && !string.IsNullOrEmpty(enemyMasterName)) + { + if (spawnEnemyArgsDirty) + { + enemyMasterNameTeamIndexEquipmentIndex = string.Join(" ", "create_master", enemyMasterName, teamIndex, equipmentIndex); + spawnEnemyArgsDirty = false; + } + int num = int.Parse(enemiesAmountDropdown.options[Mathf.Min(enemiesAmountDropdown.options.Count - 1, enemiesAmountDropdown.value)].text); + for (int i = 0; i < num; i++) + { + RoR2.Console.instance.SubmitCmd(NetworkUser.readOnlyLocalPlayersList[0], enemyMasterNameTeamIndexEquipmentIndex, recordSubmit: true); + spawnEnemyText.SetText(enemyMasterNameTeamIndexEquipmentIndex); + } + } + } + + public void SetEnemyMasterName() + { + string text = masterNameDropdown.options[Mathf.Min(masterNameDropdown.options.Count - 1, masterNameDropdown.value)].text; + if (string.IsNullOrEmpty(text) || enemyMasterName == text || MasterCatalog.FindMasterIndex(text) == MasterCatalog.MasterIndex.none) + { + Debug.LogWarning("Invalid newEnemyMaster: " + text); + return; + } + enemyMasterName = text; + spawnEnemyArgsDirty = true; + enemyName.SetText(enemyMasterName); + } + + public void SetSceneTravelName() + { + string text = stageListDropdown.options[Mathf.Min(stageListDropdown.options.Count - 1, stageListDropdown.value)].text; + if (!string.IsNullOrEmpty(text)) + { + RoR2.Console.instance.SubmitCmd(null, "set_scene " + text); + } + } + + public void SetTeamIndex(string newTeamIndex) + { + if (string.IsNullOrEmpty(newTeamIndex) || teamIndex == newTeamIndex || !Enum.TryParse(newTeamIndex, ignoreCase: true, out var _)) + { + Debug.LogWarning("Invalid newTeamIndex: " + newTeamIndex); + return; + } + teamIndex = newTeamIndex; + spawnEnemyArgsDirty = true; + teamText.SetText(teamIndex); + } + + public void SetCurrentEquipment(string newEquipment) + { + if (string.IsNullOrEmpty(newEquipment) || equipmentIndex == newEquipment || EquipmentCatalog.FindEquipmentIndex(newEquipment) == EquipmentIndex.None) + { + Debug.LogWarning("Invalid newEquipment: " + newEquipment); + return; + } + equipmentIndex = newEquipment; + spawnEnemyArgsDirty = true; + affixText.SetText(equipmentIndex); + } + + public void SetUppercase() + { + isUpper = true; + } + + public void SetLowercase() + { + isUpper = false; + } + + public void BackspaceMiscCommand() + { + miscCommand.Remove(miscCommand.Length - 1, 1); + miscCommandLabel.SetText(miscCommand); + } + + public void AppendMiscCommand(string stringToAdd) + { + miscCommand.Append(isUpper ? stringToAdd.ToUpper() : stringToAdd.ToLower()); + miscCommandLabel.SetText(miscCommand); + } + + public void SubmitMiscCommand() + { + string text = miscCommand.ToString(); + if (string.IsNullOrEmpty(text)) + { + string text2 = "Invalid command sequence: " + text + ". Enter a valid command sequence before submitting a command."; + Debug.LogWarning(text2); + miscCommandLabel.SetText(text2); + return; + } + if (localUser == null && NetworkUser.readOnlyLocalPlayersList != null && NetworkUser.readOnlyLocalPlayersList.Count > 0) + { + localUser = NetworkUser.readOnlyLocalPlayersList[0]; + } + RoR2.Console.instance.SubmitCmd(localUser, text, recordSubmit: true); + } + + public void ClearMiscCommand() + { + miscCommand.Clear(); + miscCommandLabel.SetText(miscCommand); + } + + public void AttemptAlternateClick() + { + if ((bool)eventSystem.currentSelectedButton) + { + AlternateButtonEvents component = eventSystem.currentSelectedButton.GetComponent(); + if ((bool)component) + { + component.InvokeAltClick(); + } + } + } + + public void AttemptTertiaryClick() + { + if ((bool)eventSystem.currentSelectedButton) + { + AlternateButtonEvents component = eventSystem.currentSelectedButton.GetComponent(); + if ((bool)component) + { + component.InvokeTertiaryClick(); + } + } + } + + private void InitializeItemsDropdown() + { + itemsNamesDropdown.options = ContentManager._itemDefs.Select((ItemDef itemDef) => new TMP_Dropdown.OptionData(itemDef.name)).ToList(); + } + + public void GiveItem() + { + string text = itemsNamesDropdown.options[Mathf.Min(itemsNamesDropdown.options.Count - 1, itemsNamesDropdown.value)].text; + int num = int.Parse(itemsAmountDropdown.options[Mathf.Min(itemsAmountDropdown.options.Count - 1, itemsAmountDropdown.value)].text); + RoR2.Console.instance.SubmitCmd(NetworkUser.readOnlyLocalPlayersList[0], $"give_item {text} {num}", recordSubmit: true); + } + + [ConCommand(commandName = "enemies_are_gods", flags = ConVarFlags.None, helpText = "EnemiesAreGods")] + private static void EnemiesAreGods(ConCommandArgs args) + { + foreach (TeamComponent teamMember in TeamComponent.GetTeamMembers(TeamIndex.Monster)) + { + HealthComponent component = teamMember.GetComponent(); + component.godMode = !component.godMode; + } + } + + public void StartLog() + { + } + + public void StopLog() + { + } + + public void Close() + { + UnityEngine.Object.Destroy(base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/DevotedLemurianController.cs b/ilspy_dump/ror2_csproj/DevotedLemurianController.cs new file mode 100644 index 0000000..eef7e39 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DevotedLemurianController.cs @@ -0,0 +1,127 @@ +using System.Collections; +using System.Collections.Generic; +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +public class DevotedLemurianController : MonoBehaviour +{ + private CharacterMaster _lemurianMaster; + + private DevotionInventoryController _devotionInventoryController; + + private ItemIndex _devotionItem; + + private int _devotedEvolutionLevel; + + private float _leashDistSq = 160000f; + + private const float minTeleportDistance = 10f; + + private const float maxTeleportDistance = 40f; + + public int DevotedEvolutionLevel + { + get + { + return _devotedEvolutionLevel; + } + set + { + _devotedEvolutionLevel = value; + } + } + + public ItemIndex DevotionItem => _devotionItem; + + public CharacterBody LemurianBody => _lemurianMaster.GetBody(); + + public Inventory LemurianInventory => _lemurianMaster.inventory; + + private void Start() + { + StartCoroutine(TryTeleport()); + } + + private bool CheckIfNeedTeleport() + { + if (!LemurianBody.hasEffectiveAuthority) + { + return false; + } + CharacterMaster characterMaster = (_lemurianMaster ? _lemurianMaster.minionOwnership.ownerMaster : null); + CharacterBody characterBody = (characterMaster ? characterMaster.GetBody() : null); + if (!characterBody) + { + return false; + } + Vector3 corePosition = characterBody.corePosition; + Vector3 corePosition2 = LemurianBody.corePosition; + if ((((bool)LemurianBody.characterMotor && LemurianBody.characterMotor.walkSpeed > 0f) || LemurianBody.moveSpeed > 0f) && (corePosition2 - corePosition).sqrMagnitude > _leashDistSq) + { + return true; + } + return false; + } + + private IEnumerator TryTeleport() + { + Debug.Log("try teleport"); + while ((bool)_lemurianMaster) + { + while (!LemurianBody || !CheckIfNeedTeleport()) + { + yield return new WaitForSeconds(1f); + } + CharacterMaster characterMaster = (_lemurianMaster ? _lemurianMaster.minionOwnership.ownerMaster : null); + CharacterBody ownerBody = characterMaster.GetBody(); + NodeGraph nodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + List list = nodeGraph.FindNodesInRangeWithFlagConditions(ownerBody.transform.position, 3f, 20f, HullMask.None, NodeFlags.None, NodeFlags.NoCharacterSpawn, preventOverhead: false); + while (list.Count == 0) + { + Debug.Log("no valid node to teleport"); + yield return new WaitForSeconds(1f); + list = nodeGraph.FindNodesInRangeWithFlagConditions(ownerBody.transform.position, 3f, 20f, HullMask.None, NodeFlags.None, NodeFlags.NoCharacterSpawn, preventOverhead: false); + } + while (list.Count > 0) + { + Debug.Log("teleporting"); + int index = Random.Range(0, list.Count); + NodeGraph.NodeIndex nodeIndex = list[index]; + if (nodeGraph.GetNodePosition(nodeIndex, out var position)) + { + TeleportHelper.TeleportBody(LemurianBody, position); + GameObject teleportEffectPrefab = Run.instance.GetTeleportEffectPrefab(LemurianBody.gameObject); + if ((bool)teleportEffectPrefab) + { + EffectManager.SimpleEffect(teleportEffectPrefab, position, Quaternion.identity, transmit: true); + } + break; + } + } + yield return new WaitForSeconds(1f); + } + Debug.Log("finish try teleport"); + } + + public void InitializeDevotedLemurian(ItemIndex itemIndex, DevotionInventoryController devotionInventoryController) + { + _devotionItem = itemIndex; + _devotionInventoryController = devotionInventoryController; + _lemurianMaster = GetComponent(); + } + + public void OnDevotedBodyDead() + { + if (_devotionInventoryController.HasItem(RoR2Content.Items.ExtraLife)) + { + _devotionInventoryController.RemoveItem(RoR2Content.Items.ExtraLife.itemIndex); + } + else + { + _devotionInventoryController.RemoveItem(_devotionItem, _devotedEvolutionLevel + 1); + _devotionInventoryController.DropScrapOnDeath(_devotionItem, LemurianBody); + } + _devotionInventoryController.UpdateAllMinions(); + } +} diff --git a/ilspy_dump/ror2_csproj/DisableOnStart.cs b/ilspy_dump/ror2_csproj/DisableOnStart.cs new file mode 100644 index 0000000..2a38cf4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DisableOnStart.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class DisableOnStart : MonoBehaviour +{ + private void Start() + { + base.gameObject.SetActive(value: false); + } +} diff --git a/ilspy_dump/ror2_csproj/DoXInYSecondsTracker.cs b/ilspy_dump/ror2_csproj/DoXInYSecondsTracker.cs new file mode 100644 index 0000000..452f627 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DoXInYSecondsTracker.cs @@ -0,0 +1,68 @@ +using System; +using HG; + +public class DoXInYSecondsTracker +{ + private readonly float[] timestamps; + + private readonly float window; + + private int lastValidCount; + + private float newestTime => timestamps[0]; + + private int requirement => timestamps.Length; + + public DoXInYSecondsTracker(int requirement, float window) + { + if (requirement < 1) + { + throw new ArgumentException("Argument must be greater than zero", "requirement"); + } + timestamps = new float[requirement]; + Clear(); + this.window = window; + } + + public void Clear() + { + for (int i = 0; i < timestamps.Length; i++) + { + timestamps[i] = float.NegativeInfinity; + } + } + + private int FindInsertionPosition(float t) + { + for (int i = 0; i < lastValidCount; i++) + { + if (timestamps[i] < t) + { + return i; + } + } + return lastValidCount; + } + + public bool Push(float t) + { + float num = t - window; + if (t < newestTime) + { + lastValidCount = timestamps.Length; + } + int num2 = lastValidCount - 1; + while (num2 >= 0 && !(num <= timestamps[num2])) + { + lastValidCount--; + num2--; + } + int num3 = FindInsertionPosition(t); + if (num3 < timestamps.Length) + { + lastValidCount++; + ArrayUtils.ArrayInsertNoResize(timestamps, lastValidCount, num3, in t); + } + return lastValidCount == requirement; + } +} diff --git a/ilspy_dump/ror2_csproj/DynamicBone.cs b/ilspy_dump/ror2_csproj/DynamicBone.cs new file mode 100644 index 0000000..8c8d7d1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DynamicBone.cs @@ -0,0 +1,613 @@ +using System.Collections.Generic; +using UnityEngine; + +[AddComponentMenu("Dynamic Bone/Dynamic Bone")] +public class DynamicBone : MonoBehaviour +{ + public enum UpdateMode + { + Normal, + AnimatePhysics, + UnscaledTime + } + + public enum FreezeAxis + { + None, + X, + Y, + Z + } + + private class Particle + { + public Transform m_Transform; + + public int m_ParentIndex = -1; + + public float m_Damping; + + public float m_Elasticity; + + public float m_Stiffness; + + public float m_Inert; + + public float m_Radius; + + public float m_BoneLength; + + public Vector3 m_Position = Vector3.zero; + + public Vector3 m_PrevPosition = Vector3.zero; + + public Vector3 m_EndOffset = Vector3.zero; + + public Vector3 m_InitLocalPosition = Vector3.zero; + + public Quaternion m_InitLocalRotation = Quaternion.identity; + } + + public Transform m_Root; + + public float m_UpdateRate = 60f; + + public UpdateMode m_UpdateMode; + + [Range(0f, 1f)] + public float m_Damping = 0.1f; + + public AnimationCurve m_DampingDistrib; + + [Range(0f, 1f)] + public float m_Elasticity = 0.1f; + + public AnimationCurve m_ElasticityDistrib; + + [Range(0f, 1f)] + public float m_Stiffness = 0.1f; + + public AnimationCurve m_StiffnessDistrib; + + [Range(0f, 1f)] + public float m_Inert; + + public AnimationCurve m_InertDistrib; + + public float m_Radius; + + public AnimationCurve m_RadiusDistrib; + + public float m_EndLength; + + public Vector3 m_EndOffset = Vector3.zero; + + public Vector3 m_Gravity = Vector3.zero; + + public Vector3 m_Force = Vector3.zero; + + public List m_Colliders; + + public List m_Exclusions; + + public FreezeAxis m_FreezeAxis; + + public bool m_DistantDisable; + + public Transform m_ReferenceObject; + + public float m_DistanceToObject = 20f; + + [Tooltip("Check this if you want the bone to be dynamic even on low performance HW")] + public bool neverOptimize; + + private Vector3 m_LocalGravity = Vector3.zero; + + private Vector3 m_ObjectMove = Vector3.zero; + + private Vector3 m_ObjectPrevPosition = Vector3.zero; + + private float m_BoneTotalLength; + + private float m_ObjectScale = 1f; + + private float m_Time; + + private float m_Weight = 1f; + + private bool m_DistantDisabled; + + private List m_Particles = new List(); + + private void Start() + { + SetupParticles(); + } + + private void FixedUpdate() + { + if (m_UpdateMode == UpdateMode.AnimatePhysics) + { + PreUpdate(); + } + } + + private void Update() + { + if (m_UpdateMode != UpdateMode.AnimatePhysics) + { + PreUpdate(); + } + } + + private void LateUpdate() + { + if (m_DistantDisable) + { + CheckDistance(); + } + if (m_Weight > 0f && (!m_DistantDisable || !m_DistantDisabled)) + { + float deltaTime = Time.deltaTime; + UpdateDynamicBones(deltaTime); + } + } + + private void PreUpdate() + { + if (m_Weight > 0f && (!m_DistantDisable || !m_DistantDisabled)) + { + InitTransforms(); + } + } + + private void CheckDistance() + { + Transform referenceObject = m_ReferenceObject; + if (referenceObject == null && (bool)Camera.main) + { + referenceObject = Camera.main.transform; + } + if (!referenceObject) + { + return; + } + bool flag = (referenceObject.position - base.transform.position).sqrMagnitude > m_DistanceToObject * m_DistanceToObject; + if (flag != m_DistantDisabled) + { + if (!flag) + { + ResetParticlesPosition(); + } + m_DistantDisabled = flag; + } + } + + private void OnEnable() + { + ResetParticlesPosition(); + } + + private void OnDisable() + { + InitTransforms(); + } + + private void OnValidate() + { + m_UpdateRate = Mathf.Max(m_UpdateRate, 0f); + m_Damping = Mathf.Clamp01(m_Damping); + m_Elasticity = Mathf.Clamp01(m_Elasticity); + m_Stiffness = Mathf.Clamp01(m_Stiffness); + m_Inert = Mathf.Clamp01(m_Inert); + m_Radius = Mathf.Max(m_Radius, 0f); + if (Application.isEditor && Application.isPlaying) + { + InitTransforms(); + SetupParticles(); + } + } + + private void OnDrawGizmosSelected() + { + if (!base.enabled || m_Root == null) + { + return; + } + if (Application.isEditor && !Application.isPlaying && base.transform.hasChanged) + { + InitTransforms(); + SetupParticles(); + } + Gizmos.color = Color.white; + for (int i = 0; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + if (particle.m_ParentIndex >= 0) + { + Particle particle2 = m_Particles[particle.m_ParentIndex]; + Gizmos.DrawLine(particle.m_Position, particle2.m_Position); + } + if (particle.m_Radius > 0f) + { + Gizmos.DrawWireSphere(particle.m_Position, particle.m_Radius * m_ObjectScale); + } + } + } + + public void SetWeight(float w) + { + if (m_Weight != w) + { + if (w == 0f) + { + InitTransforms(); + } + else if (m_Weight == 0f) + { + ResetParticlesPosition(); + } + m_Weight = w; + } + } + + public float GetWeight() + { + return m_Weight; + } + + private void UpdateDynamicBones(float t) + { + if (m_Root == null) + { + return; + } + m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x); + m_ObjectMove = base.transform.position - m_ObjectPrevPosition; + m_ObjectPrevPosition = base.transform.position; + int num = 1; + if (m_UpdateRate > 0f) + { + float num2 = 1f / m_UpdateRate; + m_Time += t; + num = 0; + while (m_Time >= num2) + { + m_Time -= num2; + if (++num >= 3) + { + m_Time = 0f; + break; + } + } + } + if (num > 0) + { + for (int i = 0; i < num; i++) + { + UpdateParticles1(); + UpdateParticles2(); + m_ObjectMove = Vector3.zero; + } + } + else + { + SkipUpdateParticles(); + } + ApplyParticlesToTransforms(); + } + + private void SetupParticles() + { + m_Particles.Clear(); + if (m_Root == null) + { + return; + } + m_LocalGravity = m_Root.InverseTransformDirection(m_Gravity); + m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x); + m_ObjectPrevPosition = base.transform.position; + m_ObjectMove = Vector3.zero; + m_BoneTotalLength = 0f; + AppendParticles(m_Root, -1, 0f); + for (int i = 0; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + particle.m_Damping = m_Damping; + particle.m_Elasticity = m_Elasticity; + particle.m_Stiffness = m_Stiffness; + particle.m_Inert = m_Inert; + particle.m_Radius = m_Radius; + if (m_BoneTotalLength > 0f) + { + float time = particle.m_BoneLength / m_BoneTotalLength; + if (m_DampingDistrib != null && m_DampingDistrib.keys.Length != 0) + { + particle.m_Damping *= m_DampingDistrib.Evaluate(time); + } + if (m_ElasticityDistrib != null && m_ElasticityDistrib.keys.Length != 0) + { + particle.m_Elasticity *= m_ElasticityDistrib.Evaluate(time); + } + if (m_StiffnessDistrib != null && m_StiffnessDistrib.keys.Length != 0) + { + particle.m_Stiffness *= m_StiffnessDistrib.Evaluate(time); + } + if (m_InertDistrib != null && m_InertDistrib.keys.Length != 0) + { + particle.m_Inert *= m_InertDistrib.Evaluate(time); + } + if (m_RadiusDistrib != null && m_RadiusDistrib.keys.Length != 0) + { + particle.m_Radius *= m_RadiusDistrib.Evaluate(time); + } + } + particle.m_Damping = Mathf.Clamp01(particle.m_Damping); + particle.m_Elasticity = Mathf.Clamp01(particle.m_Elasticity); + particle.m_Stiffness = Mathf.Clamp01(particle.m_Stiffness); + particle.m_Inert = Mathf.Clamp01(particle.m_Inert); + particle.m_Radius = Mathf.Max(particle.m_Radius, 0f); + } + } + + private void AppendParticles(Transform b, int parentIndex, float boneLength) + { + Particle particle = new Particle(); + particle.m_Transform = b; + particle.m_ParentIndex = parentIndex; + if ((bool)b) + { + particle.m_Position = (particle.m_PrevPosition = b.position); + particle.m_InitLocalPosition = b.localPosition; + particle.m_InitLocalRotation = b.localRotation; + } + else + { + Transform transform = m_Particles[parentIndex].m_Transform; + if (m_EndLength > 0f) + { + Transform parent = transform.parent; + if ((bool)parent) + { + particle.m_EndOffset = transform.InverseTransformPoint(transform.position * 2f - parent.position) * m_EndLength; + } + else + { + particle.m_EndOffset = new Vector3(m_EndLength, 0f, 0f); + } + } + else + { + particle.m_EndOffset = transform.InverseTransformPoint(base.transform.TransformDirection(m_EndOffset) + transform.position); + } + particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset)); + } + if (parentIndex >= 0) + { + boneLength += (m_Particles[parentIndex].m_Transform.position - particle.m_Position).magnitude; + particle.m_BoneLength = boneLength; + m_BoneTotalLength = Mathf.Max(m_BoneTotalLength, boneLength); + } + int count = m_Particles.Count; + m_Particles.Add(particle); + if (!b) + { + return; + } + for (int i = 0; i < b.childCount; i++) + { + bool flag = false; + if (m_Exclusions != null) + { + for (int j = 0; j < m_Exclusions.Count; j++) + { + if (m_Exclusions[j] == b.GetChild(i)) + { + flag = true; + break; + } + } + } + if (!flag) + { + AppendParticles(b.GetChild(i), count, boneLength); + } + } + if (b.childCount == 0 && (m_EndLength > 0f || m_EndOffset != Vector3.zero)) + { + AppendParticles(null, count, boneLength); + } + } + + private void InitTransforms() + { + for (int i = 0; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + if ((bool)particle.m_Transform) + { + particle.m_Transform.localPosition = particle.m_InitLocalPosition; + particle.m_Transform.localRotation = particle.m_InitLocalRotation; + } + } + } + + private void ResetParticlesPosition() + { + for (int i = 0; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + if ((bool)particle.m_Transform) + { + particle.m_Position = (particle.m_PrevPosition = particle.m_Transform.position); + continue; + } + Transform transform = m_Particles[particle.m_ParentIndex].m_Transform; + particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset)); + } + m_ObjectPrevPosition = base.transform.position; + } + + private void UpdateParticles1() + { + Vector3 gravity = m_Gravity; + Vector3 normalized = m_Gravity.normalized; + Vector3 lhs = m_Root.TransformDirection(m_LocalGravity); + Vector3 vector = normalized * Mathf.Max(Vector3.Dot(lhs, normalized), 0f); + gravity -= vector; + gravity = (gravity + m_Force) * m_ObjectScale; + for (int i = 0; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + if (particle.m_ParentIndex >= 0) + { + Vector3 vector2 = particle.m_Position - particle.m_PrevPosition; + Vector3 vector3 = m_ObjectMove * particle.m_Inert; + particle.m_PrevPosition = particle.m_Position + vector3; + particle.m_Position += vector2 * (1f - particle.m_Damping) + gravity + vector3; + } + else + { + particle.m_PrevPosition = particle.m_Position; + particle.m_Position = particle.m_Transform.position; + } + } + } + + private void UpdateParticles2() + { + Plane plane = default(Plane); + for (int i = 1; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + Particle particle2 = m_Particles[particle.m_ParentIndex]; + if (!particle2.m_Transform) + { + continue; + } + float num = ((!particle.m_Transform) ? particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude : (particle2.m_Transform.position - particle.m_Transform.position).magnitude); + float num2 = Mathf.Lerp(1f, particle.m_Stiffness, m_Weight); + if (num2 > 0f || particle.m_Elasticity > 0f) + { + Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix; + localToWorldMatrix.SetColumn(3, particle2.m_Position); + Vector3 vector = ((!particle.m_Transform) ? localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset) : localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition)); + Vector3 vector2 = vector - particle.m_Position; + particle.m_Position += vector2 * particle.m_Elasticity; + if (num2 > 0f) + { + vector2 = vector - particle.m_Position; + float magnitude = vector2.magnitude; + float num3 = num * (1f - num2) * 2f; + if (magnitude > num3) + { + particle.m_Position += vector2 * ((magnitude - num3) / magnitude); + } + } + } + if (m_Colliders != null) + { + float particleRadius = particle.m_Radius * m_ObjectScale; + for (int j = 0; j < m_Colliders.Count; j++) + { + DynamicBoneCollider dynamicBoneCollider = m_Colliders[j]; + if ((bool)dynamicBoneCollider && dynamicBoneCollider.enabled) + { + dynamicBoneCollider.Collide(ref particle.m_Position, particleRadius); + } + } + } + if (m_FreezeAxis != 0) + { + switch (m_FreezeAxis) + { + case FreezeAxis.X: + plane.SetNormalAndPosition(particle2.m_Transform.right, particle2.m_Position); + break; + case FreezeAxis.Y: + plane.SetNormalAndPosition(particle2.m_Transform.up, particle2.m_Position); + break; + case FreezeAxis.Z: + plane.SetNormalAndPosition(particle2.m_Transform.forward, particle2.m_Position); + break; + } + particle.m_Position -= plane.normal * plane.GetDistanceToPoint(particle.m_Position); + } + Vector3 vector3 = particle2.m_Position - particle.m_Position; + float magnitude2 = vector3.magnitude; + if (magnitude2 > 0f) + { + particle.m_Position += vector3 * ((magnitude2 - num) / magnitude2); + } + } + } + + private void SkipUpdateParticles() + { + for (int i = 0; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + if (particle.m_ParentIndex >= 0) + { + particle.m_PrevPosition += m_ObjectMove; + particle.m_Position += m_ObjectMove; + Particle particle2 = m_Particles[particle.m_ParentIndex]; + if (!particle2.m_Transform) + { + continue; + } + float num = ((!particle.m_Transform) ? particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude : (particle2.m_Transform.position - particle.m_Transform.position).magnitude); + float num2 = Mathf.Lerp(1f, particle.m_Stiffness, m_Weight); + if (num2 > 0f) + { + Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix; + localToWorldMatrix.SetColumn(3, particle2.m_Position); + Vector3 vector = ((!particle.m_Transform) ? localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset) : localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition)); + Vector3 vector2 = vector - particle.m_Position; + float magnitude = vector2.magnitude; + float num3 = num * (1f - num2) * 2f; + if (magnitude > num3) + { + particle.m_Position += vector2 * ((magnitude - num3) / magnitude); + } + } + Vector3 vector3 = particle2.m_Position - particle.m_Position; + float magnitude2 = vector3.magnitude; + if (magnitude2 > 0f) + { + particle.m_Position += vector3 * ((magnitude2 - num) / magnitude2); + } + } + else if ((bool)particle.m_Transform) + { + particle.m_PrevPosition = particle.m_Position; + particle.m_Position = particle.m_Transform.position; + } + } + } + + private static Vector3 MirrorVector(Vector3 v, Vector3 axis) + { + return v - axis * (Vector3.Dot(v, axis) * 2f); + } + + private void ApplyParticlesToTransforms() + { + for (int i = 1; i < m_Particles.Count; i++) + { + Particle particle = m_Particles[i]; + Particle particle2 = m_Particles[particle.m_ParentIndex]; + if (particle2.m_Transform.childCount <= 1) + { + Vector3 direction = ((!particle.m_Transform) ? particle.m_EndOffset : particle.m_Transform.localPosition); + Vector3 toDirection = particle.m_Position - particle2.m_Position; + Quaternion quaternion = Quaternion.FromToRotation(particle2.m_Transform.TransformDirection(direction), toDirection); + particle2.m_Transform.rotation = quaternion * particle2.m_Transform.rotation; + } + if ((bool)particle.m_Transform) + { + particle.m_Transform.position = particle.m_Position; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/DynamicBoneCollider.cs b/ilspy_dump/ror2_csproj/DynamicBoneCollider.cs new file mode 100644 index 0000000..64153a7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/DynamicBoneCollider.cs @@ -0,0 +1,227 @@ +using UnityEngine; + +[AddComponentMenu("Dynamic Bone/Dynamic Bone Collider")] +public class DynamicBoneCollider : MonoBehaviour +{ + public enum Direction + { + X, + Y, + Z + } + + public enum Bound + { + Outside, + Inside + } + + public Vector3 m_Center = Vector3.zero; + + public float m_Radius = 0.5f; + + public float m_Height; + + public Direction m_Direction; + + public Bound m_Bound; + + private void OnValidate() + { + m_Radius = Mathf.Max(m_Radius, 0f); + m_Height = Mathf.Max(m_Height, 0f); + } + + public void Collide(ref Vector3 particlePosition, float particleRadius) + { + float num = m_Radius * Mathf.Abs(base.transform.lossyScale.x); + float num2 = m_Height * 0.5f - m_Radius; + if (num2 <= 0f) + { + if (m_Bound == Bound.Outside) + { + OutsideSphere(ref particlePosition, particleRadius, base.transform.TransformPoint(m_Center), num); + } + else + { + InsideSphere(ref particlePosition, particleRadius, base.transform.TransformPoint(m_Center), num); + } + return; + } + Vector3 center = m_Center; + Vector3 center2 = m_Center; + switch (m_Direction) + { + case Direction.X: + center.x -= num2; + center2.x += num2; + break; + case Direction.Y: + center.y -= num2; + center2.y += num2; + break; + case Direction.Z: + center.z -= num2; + center2.z += num2; + break; + } + if (m_Bound == Bound.Outside) + { + OutsideCapsule(ref particlePosition, particleRadius, base.transform.TransformPoint(center), base.transform.TransformPoint(center2), num); + } + else + { + InsideCapsule(ref particlePosition, particleRadius, base.transform.TransformPoint(center), base.transform.TransformPoint(center2), num); + } + } + + private static void OutsideSphere(ref Vector3 particlePosition, float particleRadius, Vector3 sphereCenter, float sphereRadius) + { + float num = sphereRadius + particleRadius; + float num2 = num * num; + Vector3 vector = particlePosition - sphereCenter; + float sqrMagnitude = vector.sqrMagnitude; + if (sqrMagnitude > 0f && sqrMagnitude < num2) + { + float num3 = Mathf.Sqrt(sqrMagnitude); + particlePosition = sphereCenter + vector * (num / num3); + } + } + + private static void InsideSphere(ref Vector3 particlePosition, float particleRadius, Vector3 sphereCenter, float sphereRadius) + { + float num = sphereRadius - particleRadius; + float num2 = num * num; + Vector3 vector = particlePosition - sphereCenter; + float sqrMagnitude = vector.sqrMagnitude; + if (sqrMagnitude > num2) + { + float num3 = Mathf.Sqrt(sqrMagnitude); + particlePosition = sphereCenter + vector * (num / num3); + } + } + + private static void OutsideCapsule(ref Vector3 particlePosition, float particleRadius, Vector3 capsuleP0, Vector3 capsuleP1, float capsuleRadius) + { + float num = capsuleRadius + particleRadius; + float num2 = num * num; + Vector3 vector = capsuleP1 - capsuleP0; + Vector3 vector2 = particlePosition - capsuleP0; + float num3 = Vector3.Dot(vector2, vector); + if (num3 <= 0f) + { + float sqrMagnitude = vector2.sqrMagnitude; + if (sqrMagnitude > 0f && sqrMagnitude < num2) + { + float num4 = Mathf.Sqrt(sqrMagnitude); + particlePosition = capsuleP0 + vector2 * (num / num4); + } + return; + } + float sqrMagnitude2 = vector.sqrMagnitude; + if (num3 >= sqrMagnitude2) + { + vector2 = particlePosition - capsuleP1; + float sqrMagnitude3 = vector2.sqrMagnitude; + if (sqrMagnitude3 > 0f && sqrMagnitude3 < num2) + { + float num5 = Mathf.Sqrt(sqrMagnitude3); + particlePosition = capsuleP1 + vector2 * (num / num5); + } + } + else if (sqrMagnitude2 > 0f) + { + num3 /= sqrMagnitude2; + vector2 -= vector * num3; + float sqrMagnitude4 = vector2.sqrMagnitude; + if (sqrMagnitude4 > 0f && sqrMagnitude4 < num2) + { + float num6 = Mathf.Sqrt(sqrMagnitude4); + particlePosition += vector2 * ((num - num6) / num6); + } + } + } + + private static void InsideCapsule(ref Vector3 particlePosition, float particleRadius, Vector3 capsuleP0, Vector3 capsuleP1, float capsuleRadius) + { + float num = capsuleRadius - particleRadius; + float num2 = num * num; + Vector3 vector = capsuleP1 - capsuleP0; + Vector3 vector2 = particlePosition - capsuleP0; + float num3 = Vector3.Dot(vector2, vector); + if (num3 <= 0f) + { + float sqrMagnitude = vector2.sqrMagnitude; + if (sqrMagnitude > num2) + { + float num4 = Mathf.Sqrt(sqrMagnitude); + particlePosition = capsuleP0 + vector2 * (num / num4); + } + return; + } + float sqrMagnitude2 = vector.sqrMagnitude; + if (num3 >= sqrMagnitude2) + { + vector2 = particlePosition - capsuleP1; + float sqrMagnitude3 = vector2.sqrMagnitude; + if (sqrMagnitude3 > num2) + { + float num5 = Mathf.Sqrt(sqrMagnitude3); + particlePosition = capsuleP1 + vector2 * (num / num5); + } + } + else if (sqrMagnitude2 > 0f) + { + num3 /= sqrMagnitude2; + vector2 -= vector * num3; + float sqrMagnitude4 = vector2.sqrMagnitude; + if (sqrMagnitude4 > num2) + { + float num6 = Mathf.Sqrt(sqrMagnitude4); + particlePosition += vector2 * ((num - num6) / num6); + } + } + } + + private void OnDrawGizmosSelected() + { + if (!base.enabled) + { + return; + } + if (m_Bound == Bound.Outside) + { + Gizmos.color = Color.yellow; + } + else + { + Gizmos.color = Color.magenta; + } + float radius = m_Radius * Mathf.Abs(base.transform.lossyScale.x); + float num = m_Height * 0.5f - m_Radius; + if (num <= 0f) + { + Gizmos.DrawWireSphere(base.transform.TransformPoint(m_Center), radius); + return; + } + Vector3 center = m_Center; + Vector3 center2 = m_Center; + switch (m_Direction) + { + case Direction.X: + center.x -= num; + center2.x += num; + break; + case Direction.Y: + center.y -= num; + center2.y += num; + break; + case Direction.Z: + center.z -= num; + center2.z += num; + break; + } + Gizmos.DrawWireSphere(base.transform.TransformPoint(center), radius); + Gizmos.DrawWireSphere(base.transform.TransformPoint(center2), radius); + } +} diff --git a/ilspy_dump/ror2_csproj/EOSTogglePopup.cs b/ilspy_dump/ror2_csproj/EOSTogglePopup.cs new file mode 100644 index 0000000..835e696 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EOSTogglePopup.cs @@ -0,0 +1,42 @@ +using System; +using RoR2; +using RoR2.UI; +using UnityEngine; + +public class EOSTogglePopup : MonoBehaviour +{ + public string titleText = "EOS_TOGGLE_POPUP_TITLE"; + + public string messageText = "EOS_TOGGLE_POPUP_MESSAGE"; + + public string closeNowButtonText = "EOS_TOGGLE_CLOSE_NOW"; + + public string closeLaterButtonText = "EOS_TOGGLE_CLOSE_LATER"; + + public void emitMessage() + { + SimpleDialogBox dialogBox = SimpleDialogBox.Create(); + Action deactiveCrossplayAndRestartFunction = delegate + { + if ((bool)dialogBox) + { + RoR2.Console.instance.SubmitCmd(null, "quit"); + } + }; + dialogBox.AddActionButton(delegate + { + deactiveCrossplayAndRestartFunction(); + }, closeNowButtonText, true); + dialogBox.AddCancelButton(closeLaterButtonText); + dialogBox.headerToken = new SimpleDialogBox.TokenParamsPair + { + token = titleText, + formatParams = Array.Empty() + }; + dialogBox.descriptionToken = new SimpleDialogBox.TokenParamsPair + { + token = messageText, + formatParams = Array.Empty() + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EclipseDifficultyMedalDisplay.cs b/ilspy_dump/ror2_csproj/EclipseDifficultyMedalDisplay.cs new file mode 100644 index 0000000..1df3c23 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EclipseDifficultyMedalDisplay.cs @@ -0,0 +1,85 @@ +using RoR2; +using UnityEngine; +using UnityEngine.UI; + +public class EclipseDifficultyMedalDisplay : MonoBehaviour +{ + [SerializeField] + private int eclipseLevel; + + [SerializeField] + private Image iconImage; + + [SerializeField] + private Sprite unearnedSprite; + + [SerializeField] + private Sprite incompleteSprite; + + [SerializeField] + private Sprite completeSprite; + + private void OnEnable() + { + UserProfile.onSurvivorPreferenceChangedGlobal += OnSurvivorPreferenceChangedGlobal; + Refresh(); + } + + private void OnDisable() + { + UserProfile.onSurvivorPreferenceChangedGlobal -= OnSurvivorPreferenceChangedGlobal; + } + + private void OnSurvivorPreferenceChangedGlobal(UserProfile userProfile) + { + Refresh(); + } + + private void Refresh() + { + LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); + SurvivorDef survivorDef = firstLocalUser?.userProfile.GetSurvivorPreference(); + if (!survivorDef) + { + return; + } + int localUserSurvivorCompletedEclipseLevel = EclipseRun.GetLocalUserSurvivorCompletedEclipseLevel(firstLocalUser, survivorDef); + if (eclipseLevel <= localUserSurvivorCompletedEclipseLevel) + { + bool flag = true; + foreach (SurvivorDef orderedSurvivorDef in SurvivorCatalog.orderedSurvivorDefs) + { + if (ShouldDisplaySurvivor(orderedSurvivorDef, firstLocalUser)) + { + localUserSurvivorCompletedEclipseLevel = EclipseRun.GetLocalUserSurvivorCompletedEclipseLevel(firstLocalUser, orderedSurvivorDef); + if (localUserSurvivorCompletedEclipseLevel < eclipseLevel) + { + flag = false; + break; + } + } + } + if (flag) + { + iconImage.sprite = completeSprite; + } + else + { + iconImage.sprite = incompleteSprite; + } + } + else + { + iconImage.sprite = unearnedSprite; + } + } + + private bool ShouldDisplaySurvivor(SurvivorDef survivorDef, LocalUser localUser) + { + if ((bool)survivorDef && !survivorDef.hidden) + { + return survivorDef.CheckUserHasRequiredEntitlement(localUser); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/ElectricEffect.cs b/ilspy_dump/ror2_csproj/ElectricEffect.cs new file mode 100644 index 0000000..b724636 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ElectricEffect.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using UnityEngine; + +public class ElectricEffect : MonoBehaviour +{ + public LineRenderer lightningLineRenderer; + + public List lightningTextures = new List(); + + private Material lineRendererMat; + + private int counter; + + private int textureNum; + + public int interval = 3; + + public float lineWidth = 1f; + + private void Start() + { + lineRendererMat = lightningLineRenderer.material; + lightningLineRenderer.startWidth = lineWidth; + lightningLineRenderer.endWidth = lineWidth; + } + + private void Update() + { + if (!(Time.timeScale > 0f)) + { + return; + } + if (counter >= interval) + { + if (textureNum == lightningTextures.Count) + { + textureNum = 0; + } + lineRendererMat.SetTexture("_MainTex", lightningTextures[textureNum]); + textureNum++; + counter = 0; + } + counter++; + } +} diff --git a/ilspy_dump/ror2_csproj/EmptyDelegate.cs b/ilspy_dump/ror2_csproj/EmptyDelegate.cs new file mode 100644 index 0000000..bcc1aea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EmptyDelegate.cs @@ -0,0 +1 @@ +public delegate void EmptyDelegate(); diff --git a/ilspy_dump/ror2_csproj/EnableCustomRenderTextureOnLight.cs b/ilspy_dump/ror2_csproj/EnableCustomRenderTextureOnLight.cs new file mode 100644 index 0000000..b4a7b69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EnableCustomRenderTextureOnLight.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +[RequireComponent(typeof(Light))] +public class EnableCustomRenderTextureOnLight : MonoBehaviour +{ + private Light targetLight; + + private bool targetLightHasCustomRenderTexture; + + private CustomRenderTexture targetLightCookie; + + private void Awake() + { + targetLight = GetComponent(); + InitRenderTexture(); + } + + private void Start() + { + SetUpdateMode(CustomRenderTextureUpdateMode.Realtime); + } + + private void InitRenderTexture() + { + if (!(targetLight == null) && !(targetLight.cookie == null) && targetLight.cookie is CustomRenderTexture) + { + targetLightHasCustomRenderTexture = true; + targetLightCookie = targetLight.cookie as CustomRenderTexture; + } + } + + private void SetUpdateMode(CustomRenderTextureUpdateMode mode) + { + if (targetLightHasCustomRenderTexture) + { + targetLightCookie.updateMode = mode; + } + } + + private void OnEnable() + { + SetUpdateMode(CustomRenderTextureUpdateMode.Realtime); + } + + private void OnDisable() + { + SetUpdateMode(CustomRenderTextureUpdateMode.OnDemand); + } + + private void OnDestroy() + { + SetUpdateMode(CustomRenderTextureUpdateMode.OnDemand); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStateManager.cs b/ilspy_dump/ror2_csproj/EntityStateManager.cs new file mode 100644 index 0000000..964d9e7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStateManager.cs @@ -0,0 +1,546 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using EntityStates; +using HG; +using HG.GeneralSerializer; +using RoR2; +using UnityEngine; +using UnityEngine.Serialization; + +public class EntityStateManager : ScriptableObject, ISerializationCallbackReceiver +{ + [Serializable] + private class StateInfo + { + [Serializable] + public class Field + { + public enum ValueType + { + Invalid, + Int, + Float, + String, + Object, + Bool, + AnimationCurve, + Vector3 + } + + [NonSerialized] + public StateInfo owner; + + [SerializeField] + private string _fieldName; + + [SerializeField] + private ValueType _valueType; + + [SerializeField] + private int _intValue; + + [SerializeField] + private float _floatValue; + + [SerializeField] + private string _stringValue; + + [SerializeField] + private UnityEngine.Object _objectValue; + + [SerializeField] + private AnimationCurve _animationCurveValue; + + [SerializeField] + private Vector3 _vector3Value; + + public ValueType valueType => _valueType; + + public int intValue => _intValue; + + public bool boolValue => _intValue != 0; + + public float floatValue => _floatValue; + + public string stringValue => _stringValue; + + public UnityEngine.Object objectValue => _objectValue; + + public AnimationCurve animationCurveValue => _animationCurveValue; + + public Vector3 vector3Value => _vector3Value; + + public object valueAsSystemObject + { + get + { + switch (_valueType) + { + case ValueType.Invalid: + return null; + case ValueType.Int: + return intValue; + case ValueType.Float: + return floatValue; + case ValueType.String: + return stringValue; + case ValueType.Object: + if (!objectValue) + { + return null; + } + return objectValue; + case ValueType.Bool: + return boolValue; + case ValueType.AnimationCurve: + return animationCurveValue; + case ValueType.Vector3: + return vector3Value; + default: + return null; + } + } + } + + public Field(string fieldName) + { + _fieldName = fieldName; + } + + public void SetFieldInfo(FieldInfo fieldInfo) + { + _fieldName = fieldInfo.Name; + ValueType valueType = ValueType.Invalid; + Type fieldType = fieldInfo.FieldType; + if (fieldType == typeof(int)) + { + valueType = ValueType.Int; + } + else if (fieldType == typeof(float)) + { + valueType = ValueType.Float; + } + else if (fieldType == typeof(string)) + { + valueType = ValueType.String; + } + else if (typeof(UnityEngine.Object).IsAssignableFrom(fieldType)) + { + valueType = ValueType.Object; + } + else if (fieldType == typeof(bool)) + { + valueType = ValueType.Bool; + } + else if (fieldType == typeof(AnimationCurve)) + { + valueType = ValueType.AnimationCurve; + } + else if (fieldType == typeof(Vector3)) + { + valueType = ValueType.Vector3; + } + if (_valueType != valueType) + { + ResetValues(); + _valueType = valueType; + } + } + + public bool MatchesFieldInfo(FieldInfo fieldInfo) + { + if (fieldInfo == null) + { + return false; + } + Type fieldType = fieldInfo.FieldType; + switch (_valueType) + { + case ValueType.Invalid: + return false; + case ValueType.Int: + return fieldType.IsAssignableFrom(typeof(int)); + case ValueType.Float: + return fieldType.IsAssignableFrom(typeof(float)); + case ValueType.String: + return fieldType.IsAssignableFrom(typeof(string)); + case ValueType.Object: + if (!(_objectValue == null)) + { + return fieldType.IsAssignableFrom(_objectValue.GetType()); + } + return true; + case ValueType.Bool: + return fieldType.IsAssignableFrom(typeof(bool)); + case ValueType.AnimationCurve: + return fieldType.IsAssignableFrom(typeof(AnimationCurve)); + case ValueType.Vector3: + return fieldType.IsAssignableFrom(typeof(Vector3)); + default: + return false; + } + } + + public void Apply(FieldInfo fieldInfo, object instance) + { + fieldInfo.SetValue(instance, valueAsSystemObject); + } + + public void ResetValues() + { + _intValue = 0; + _floatValue = 0f; + _stringValue = null; + _objectValue = null; + _animationCurveValue = null; + _vector3Value = Vector3.zero; + } + + public void SetValue(int value) + { + ResetValues(); + _valueType = ValueType.Int; + _intValue = value; + } + + public void SetValue(float value) + { + ResetValues(); + _valueType = ValueType.Float; + _floatValue = value; + } + + public void SetValue(string value) + { + ResetValues(); + _valueType = ValueType.String; + _stringValue = value; + } + + public void SetValue(UnityEngine.Object value) + { + ResetValues(); + _valueType = ValueType.Object; + _objectValue = value; + } + + public void SetValue(bool value) + { + ResetValues(); + _valueType = ValueType.Bool; + _intValue = (value ? 1 : 0); + } + + public void SetValue(AnimationCurve value) + { + ResetValues(); + _valueType = ValueType.AnimationCurve; + _animationCurveValue = value; + } + + public void SetValue(Vector3 value) + { + ResetValues(); + _valueType = ValueType.Vector3; + _vector3Value = value; + } + + public string GetFieldName() + { + return _fieldName; + } + + public FieldInfo GetFieldInfo() + { + return owner?.serializedType.stateType?.GetField(_fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); + } + } + + private struct FieldValuePair + { + public FieldInfo fieldInfo; + + public object value; + } + + public SerializableEntityStateType serializedType; + + [FormerlySerializedAs("stateStaticFieldList")] + [SerializeField] + private List stateFieldList = new List(); + + private const BindingFlags defaultInstanceBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; + + private const BindingFlags defaultStaticBindingFlags = BindingFlags.Static | BindingFlags.Public; + + private static bool FieldHasSerializeAttribute(FieldInfo fieldInfo) + { + return CustomAttributeExtensions.GetCustomAttributes(fieldInfo, inherit: true).Any(); + } + + private static bool FieldLacksNonSerializedAttribute(FieldInfo fieldInfo) + { + return !CustomAttributeExtensions.GetCustomAttributes(fieldInfo, inherit: true).Any(); + } + + public void SetStateType(Type stateType) + { + serializedType.stateType = stateType; + stateType = serializedType.stateType; + if (stateType == null) + { + return; + } + IEnumerable first = stateType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Where(FieldHasSerializeAttribute); + IEnumerable second = (from fieldInfo in stateType.GetFields(BindingFlags.Static | BindingFlags.Public) + where fieldInfo.DeclaringType == stateType + select fieldInfo).Where(FieldLacksNonSerializedAttribute); + List list = first.Concat(second).ToList(); + Dictionary dictionary = new Dictionary(); + foreach (FieldInfo fieldInfo2 in list) + { + Field field = stateFieldList.Find((Field item) => item.GetFieldName() == fieldInfo2.Name); + if (field == null) + { + Debug.LogFormat("Could not find field {0}.{1}. Initializing new field.", stateType.Name, fieldInfo2.Name); + field = new Field(fieldInfo2.Name); + } + dictionary[fieldInfo2] = field; + } + stateFieldList.Clear(); + foreach (FieldInfo item in list) + { + Field field2 = dictionary[item]; + field2.owner = this; + field2.SetFieldInfo(item); + stateFieldList.Add(field2); + } + } + + public void RefreshStateType() + { + SetStateType(serializedType.stateType); + } + + public void ApplyStatic() + { + Type stateType = serializedType.stateType; + if (!(stateType != null)) + { + return; + } + foreach (Field stateField in stateFieldList) + { + FieldInfo field = stateType.GetField(stateField.GetFieldName(), BindingFlags.Static | BindingFlags.Public); + if (stateField.MatchesFieldInfo(field) && field.IsStatic) + { + stateField.Apply(field, null); + } + } + } + + public Action GenerateInstanceFieldInitializerDelegate() + { + Type stateType = serializedType.stateType; + if (stateType == null) + { + return null; + } + List list = new List(); + for (int i = 0; i < stateFieldList.Count; i++) + { + Field field = stateFieldList[i]; + FieldValuePair fieldValuePair = default(FieldValuePair); + fieldValuePair.fieldInfo = stateType.GetField(field.GetFieldName(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); + fieldValuePair.value = field.valueAsSystemObject; + FieldValuePair item = fieldValuePair; + if (!(item.fieldInfo == null)) + { + list.Add(item); + } + } + FieldValuePair[] fieldValuePairs = list.ToArray(); + if (fieldValuePairs.Length == 0) + { + return null; + } + return delegate(EntityState entityState) + { + for (int j = 0; j < fieldValuePairs.Length; j++) + { + FieldValuePair fieldValuePair2 = fieldValuePairs[j]; + fieldValuePair2.fieldInfo.SetValue(entityState, fieldValuePair2.value); + } + }; + } + + public Field FindField(string fieldName) + { + return stateFieldList.Find((Field value) => value.GetFieldName() == fieldName); + } + + public bool IsValid() + { + return serializedType.stateType != null; + } + + public IList GetFields() + { + return stateFieldList.AsReadOnly(); + } + } + + [SerializeField] + private List stateInfoList = new List(); + + [HideInInspector] + [SerializeField] + private string endMarker = "GIT_END"; + + private static readonly Dictionary> instanceFieldInitializers = new Dictionary>(); + + private StateInfo GetStateInfo(Type stateType) + { + if (stateType == null || !stateType.IsSubclassOf(typeof(EntityState))) + { + return null; + } + StateInfo stateInfo = stateInfoList.Find((StateInfo currentItem) => currentItem.serializedType.stateType == stateType); + if (stateInfo == null) + { + stateInfo = new StateInfo(); + stateInfo.SetStateType(stateType); + stateInfoList.Add(stateInfo); + } + return stateInfo; + } + + private void ApplyStatic() + { + foreach (StateInfo stateInfo in stateInfoList) + { + stateInfo.ApplyStatic(); + } + } + + public void Initialize() + { + } + + private static void SetEntityStateConfigurations(EntityStateConfiguration[] newEntityStateConfigurations) + { + EntityStateConfiguration[] array = ArrayUtils.Clone(newEntityStateConfigurations); + Array.Sort(array, (EntityStateConfiguration a, EntityStateConfiguration b) => a.name.CompareTo(b.name)); + for (int i = 0; i < array.Length; i++) + { + array[i].ApplyStatic(); + } + instanceFieldInitializers.Clear(); + foreach (EntityStateConfiguration entityStateConfiguration in array) + { + Action action = entityStateConfiguration.BuildInstanceInitializer(); + if (action != null) + { + instanceFieldInitializers[(Type)entityStateConfiguration.targetType] = action; + } + } + } + + void ISerializationCallbackReceiver.OnBeforeSerialize() + { + foreach (StateInfo stateInfo in stateInfoList) + { + stateInfo.RefreshStateType(); + } + stateInfoList.RemoveAll((StateInfo stateInfo) => !stateInfo.IsValid()); + } + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + foreach (StateInfo stateInfo in stateInfoList) + { + stateInfo.RefreshStateType(); + } + } + + private void GenerateInstanceFieldInitializers() + { + instanceFieldInitializers.Clear(); + foreach (StateInfo stateInfo in stateInfoList) + { + Type stateType = stateInfo.serializedType.stateType; + if (!(stateType == null)) + { + Action action = stateInfo.GenerateInstanceFieldInitializerDelegate(); + if (action != null) + { + instanceFieldInitializers.Add(stateType, action); + } + } + } + } + + public static void InitializeStateFields(EntityState entityState) + { + instanceFieldInitializers.TryGetValue(entityState.GetType(), out var value); + value?.Invoke(entityState); + } + + [ContextMenu("Migrate to individual assets")] + public void MigrateToEntityStateTypes() + { + List list = new List(); + foreach (StateInfo stateInfo in stateInfoList) + { + if (MigrateToEntityStateType(stateInfo)) + { + list.Add(stateInfo); + } + } + foreach (StateInfo item in list) + { + _ = item; + } + foreach (Type item2 in from t in typeof(EntityState).Assembly.GetTypes() + where typeof(EntityState).IsAssignableFrom(t) + select t) + { + GetOrCreateEntityStateSerializer(item2); + } + } + + private EntityStateConfiguration GetOrCreateEntityStateSerializer(Type type) + { + return null; + } + + private bool MigrateToEntityStateType(StateInfo stateInfo) + { + Type stateType = stateInfo.serializedType.stateType; + if (stateType == null) + { + Debug.LogWarningFormat("Could not migrate type named \"{0}\": Type could not be found.", typeof(SerializableEntityStateType).GetField("_typeName", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(stateInfo.serializedType)); + return false; + } + EntityStateConfiguration orCreateEntityStateSerializer = GetOrCreateEntityStateSerializer(stateType); + foreach (StateInfo.Field field2 in stateInfo.GetFields()) + { + string fieldName = field2.GetFieldName(); + FieldInfo field = stateType.GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + ref SerializedField orCreateField = ref orCreateEntityStateSerializer.serializedFieldsCollection.GetOrCreateField(fieldName); + orCreateField.fieldName = fieldName; + try + { + orCreateField.fieldValue.SetValue(field, field2.valueAsSystemObject); + } + catch (Exception message) + { + Debug.LogError(message); + } + } + EditorUtil.SetDirty(orCreateEntityStateSerializer); + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Combat.cs b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Combat.cs new file mode 100644 index 0000000..790c2a1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Combat.cs @@ -0,0 +1,279 @@ +using RoR2; +using RoR2.CharacterAI; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.AI.Walker; + +public class Combat : BaseAIState +{ + private float strafeDirection; + + private const float strafeDuration = 0.25f; + + private float strafeTimer; + + private float activeSoundTimer; + + private float aiUpdateTimer; + + public float timeChasing; + + private const float minUpdateInterval = 1f / 6f; + + private const float maxUpdateInterval = 0.2f; + + private AISkillDriver dominantSkillDriver; + + protected bool currentSkillMeetsActivationConditions; + + protected SkillSlot currentSkillSlot = SkillSlot.None; + + protected Vector3 myBodyFootPosition; + + private float lastPathUpdate; + + private float fallbackNodeStartAge; + + private readonly float fallbackNodeDuration = 4f; + + public override void OnEnter() + { + base.OnEnter(); + activeSoundTimer = Random.Range(3f, 8f); + if ((bool)base.ai) + { + lastPathUpdate = base.ai.broadNavigationAgent.output.lastPathUpdate; + base.ai.broadNavigationAgent.InvalidatePath(); + } + fallbackNodeStartAge = float.NegativeInfinity; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.ai || !base.body) + { + return; + } + float deltaTime = GetDeltaTime(); + aiUpdateTimer -= deltaTime; + strafeTimer -= deltaTime; + UpdateFootPosition(); + if (aiUpdateTimer <= 0f) + { + aiUpdateTimer = BaseAIState.cvAIUpdateInterval.value; + UpdateAI(BaseAIState.cvAIUpdateInterval.value); + if (!dominantSkillDriver) + { + outer.SetNextState(new LookBusy()); + } + } + UpdateBark(); + } + + protected void UpdateFootPosition() + { + myBodyFootPosition = base.body.footPosition; + BroadNavigationSystem.Agent broadNavigationAgent = base.ai.broadNavigationAgent; + broadNavigationAgent.currentPosition = myBodyFootPosition; + } + + protected void UpdateAI(float deltaTime) + { + BaseAI.SkillDriverEvaluation skillDriverEvaluation = base.ai.skillDriverEvaluation; + dominantSkillDriver = skillDriverEvaluation.dominantSkillDriver; + currentSkillSlot = SkillSlot.None; + currentSkillMeetsActivationConditions = false; + bodyInputs.moveVector = Vector3.zero; + AISkillDriver.MovementType movementType = AISkillDriver.MovementType.Stop; + float num = 1f; + bool flag = false; + bool flag2 = false; + bool flag3 = false; + if (!base.body || !base.bodyInputBank) + { + return; + } + if ((bool)dominantSkillDriver) + { + movementType = dominantSkillDriver.movementType; + currentSkillSlot = dominantSkillDriver.skillSlot; + flag = dominantSkillDriver.activationRequiresTargetLoS; + flag2 = dominantSkillDriver.activationRequiresAimTargetLoS; + flag3 = dominantSkillDriver.activationRequiresAimConfirmation; + num = dominantSkillDriver.moveInputScale; + } + Vector3 position = base.bodyTransform.position; + _ = base.bodyInputBank.aimOrigin; + BroadNavigationSystem.Agent broadNavigationAgent = base.ai.broadNavigationAgent; + BroadNavigationSystem.AgentOutput output = broadNavigationAgent.output; + BaseAI.Target target = skillDriverEvaluation.target; + if ((bool)target?.gameObject) + { + target.GetBullseyePosition(out var position2); + Vector3 vector = position2; + if (fallbackNodeStartAge + fallbackNodeDuration < base.fixedAge) + { + base.ai.SetGoalPosition(target); + } + Vector3 targetPosition = position; + bool allowWalkOffCliff = true; + Vector3 vector2 = ((!dominantSkillDriver || !dominantSkillDriver.ignoreNodeGraph) ? (output.nextPosition ?? myBodyFootPosition) : ((!base.body.isFlying) ? vector : position2)); + Vector3 vector3 = (vector2 - myBodyFootPosition).normalized * 10f; + Vector3 vector4 = Vector3.Cross(Vector3.up, vector3); + switch (movementType) + { + case AISkillDriver.MovementType.ChaseMoveTarget: + targetPosition = vector2 + (position - myBodyFootPosition); + break; + case AISkillDriver.MovementType.FleeMoveTarget: + targetPosition -= vector3; + break; + case AISkillDriver.MovementType.StrafeMovetarget: + if (strafeTimer <= 0f) + { + if (strafeDirection == 0f) + { + strafeDirection = ((Random.Range(0, 1) == 0) ? (-1f) : 1f); + } + strafeTimer = 0.25f; + } + targetPosition += vector4 * strafeDirection; + allowWalkOffCliff = false; + break; + } + base.ai.localNavigator.targetPosition = targetPosition; + base.ai.localNavigator.allowWalkOffCliff = allowWalkOffCliff; + base.ai.localNavigator.Update(deltaTime); + if (base.ai.localNavigator.wasObstructedLastUpdate) + { + strafeDirection *= -1f; + } + bodyInputs.moveVector = base.ai.localNavigator.moveVector; + bodyInputs.moveVector *= num; + if (!flag3 || base.ai.hasAimConfirmation) + { + bool flag4 = true; + if (skillDriverEvaluation.target == skillDriverEvaluation.aimTarget && flag && flag2) + { + flag2 = false; + } + if (flag4 && flag) + { + flag4 = skillDriverEvaluation.target.TestLOSNow(); + } + if (flag4 && flag2) + { + flag4 = skillDriverEvaluation.aimTarget.TestLOSNow(); + } + if (flag4) + { + currentSkillMeetsActivationConditions = true; + } + } + } + if (output.lastPathUpdate > lastPathUpdate && !output.targetReachable && fallbackNodeStartAge + fallbackNodeDuration < base.fixedAge) + { + broadNavigationAgent.goalPosition = PickRandomNearbyReachablePosition(); + broadNavigationAgent.InvalidatePath(); + } + lastPathUpdate = output.lastPathUpdate; + } + + public override BaseAI.BodyInputs GenerateBodyInputs(in BaseAI.BodyInputs previousBodyInputs) + { + bool pressSkill = false; + bool pressSkill2 = false; + bool pressSkill3 = false; + bool pressSkill4 = false; + if ((bool)base.bodyInputBank) + { + AISkillDriver.ButtonPressType buttonPressType = AISkillDriver.ButtonPressType.Abstain; + if ((bool)dominantSkillDriver) + { + buttonPressType = dominantSkillDriver.buttonPressType; + } + bool flag = false; + switch (currentSkillSlot) + { + case SkillSlot.Primary: + flag = previousBodyInputs.pressSkill1; + break; + case SkillSlot.Secondary: + flag = previousBodyInputs.pressSkill2; + break; + case SkillSlot.Utility: + flag = previousBodyInputs.pressSkill3; + break; + case SkillSlot.Special: + flag = previousBodyInputs.pressSkill4; + break; + } + bool flag2 = currentSkillMeetsActivationConditions; + switch (buttonPressType) + { + case AISkillDriver.ButtonPressType.Abstain: + flag2 = false; + break; + case AISkillDriver.ButtonPressType.TapContinuous: + flag2 = flag2 && !flag; + break; + } + switch (currentSkillSlot) + { + case SkillSlot.Primary: + pressSkill = flag2; + break; + case SkillSlot.Secondary: + pressSkill2 = flag2; + break; + case SkillSlot.Utility: + pressSkill3 = flag2; + break; + case SkillSlot.Special: + pressSkill4 = flag2; + break; + } + } + bodyInputs.pressSkill1 = pressSkill; + bodyInputs.pressSkill2 = pressSkill2; + bodyInputs.pressSkill3 = pressSkill3; + bodyInputs.pressSkill4 = pressSkill4; + bodyInputs.pressSprint = false; + bodyInputs.pressActivateEquipment = false; + bodyInputs.desiredAimDirection = Vector3.zero; + if ((bool)dominantSkillDriver) + { + bodyInputs.pressSprint = dominantSkillDriver.shouldSprint; + bodyInputs.pressActivateEquipment = dominantSkillDriver.shouldFireEquipment && !previousBodyInputs.pressActivateEquipment; + AISkillDriver.AimType aimType = dominantSkillDriver.aimType; + BaseAI.Target aimTarget = base.ai.skillDriverEvaluation.aimTarget; + if (aimType == AISkillDriver.AimType.MoveDirection) + { + AimInDirection(ref bodyInputs, bodyInputs.moveVector); + } + if (aimTarget != null) + { + AimAt(ref bodyInputs, aimTarget); + } + } + ModifyInputsForJumpIfNeccessary(ref bodyInputs); + return bodyInputs; + } + + protected void UpdateBark() + { + activeSoundTimer -= GetDeltaTime(); + if (activeSoundTimer <= 0f) + { + activeSoundTimer = Random.Range(3f, 8f); + base.body.CallRpcBark(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Guard.cs b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Guard.cs new file mode 100644 index 0000000..7dcf54f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Guard.cs @@ -0,0 +1,14 @@ +namespace EntityStates.AI.Walker; + +public class Guard : LookBusy +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + base.fixedAge = 0f; + } + + protected override void PickNewTargetLookDirection() + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/LookBusy.cs b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/LookBusy.cs new file mode 100644 index 0000000..a753de0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/LookBusy.cs @@ -0,0 +1,94 @@ +using RoR2; +using RoR2.CharacterAI; +using UnityEngine; + +namespace EntityStates.AI.Walker; + +public class LookBusy : BaseAIState +{ + private const float minDuration = 2f; + + private const float maxDuration = 7f; + + private Vector3 targetPosition; + + private float duration; + + private float lookTimer; + + private const float minLookDuration = 0.5f; + + private const float maxLookDuration = 4f; + + private const int lookTries = 4; + + private const float lookRaycastLength = 25f; + + protected virtual void PickNewTargetLookDirection() + { + if ((bool)base.bodyInputBank) + { + float num = 0f; + Vector3 aimOrigin = base.bodyInputBank.aimOrigin; + for (int i = 0; i < 4; i++) + { + Vector3 onUnitSphere = Random.onUnitSphere; + float num2 = 25f; + if (Physics.Raycast(new Ray(aimOrigin, onUnitSphere), out var hitInfo, 25f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + num2 = hitInfo.distance; + } + if (num2 > num) + { + num = num2; + bodyInputs.desiredAimDirection = onUnitSphere; + } + } + } + lookTimer = Random.Range(0.5f, 4f); + } + + public override void OnEnter() + { + base.OnEnter(); + duration = Random.Range(2f, 7f); + base.bodyInputBank.moveVector = Vector3.zero; + base.bodyInputBank.jump.PushState(newState: false); + PickNewTargetLookDirection(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.ai || !base.body) + { + return; + } + if ((bool)base.ai.skillDriverEvaluation.dominantSkillDriver) + { + outer.SetNextState(new Combat()); + } + if (base.ai.hasAimConfirmation) + { + lookTimer -= GetDeltaTime(); + if (lookTimer <= 0f) + { + PickNewTargetLookDirection(); + } + } + if (base.fixedAge >= duration) + { + outer.SetNextState(new Wander()); + } + } + + public override BaseAI.BodyInputs GenerateBodyInputs(in BaseAI.BodyInputs previousBodyInputs) + { + return bodyInputs; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Wander.cs b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Wander.cs new file mode 100644 index 0000000..6c7e290 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AI.Walker/Wander.cs @@ -0,0 +1,135 @@ +using RoR2; +using RoR2.CharacterAI; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.AI.Walker; + +public class Wander : BaseAIState +{ + private Vector3? targetPosition; + + private float lookTimer; + + private const float minLookDuration = 0.5f; + + private const float maxLookDuration = 4f; + + private const int lookTries = 1; + + private const float lookRaycastLength = 25f; + + private Vector3 targetLookPosition; + + private float aiUpdateTimer; + + public override void Reset() + { + base.Reset(); + targetPosition = Vector3.zero; + lookTimer = 0f; + targetLookPosition = Vector3.zero; + } + + private void PickNewTargetLookPosition() + { + if ((bool)base.bodyInputBank) + { + float num = 0f; + Vector3 aimOrigin = base.bodyInputBank.aimOrigin; + Vector3 vector = base.bodyInputBank.moveVector; + if (vector == Vector3.zero) + { + vector = Random.onUnitSphere; + } + for (int i = 0; i < 1; i++) + { + Vector3 direction = Util.ApplySpread(vector, 0f, 60f, 0f, 0f); + float num2 = 25f; + Ray ray = new Ray(aimOrigin, direction); + if (Physics.Raycast(ray, out var hitInfo, 25f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + num2 = hitInfo.distance; + } + if (num2 > num) + { + num = num2; + targetLookPosition = ray.GetPoint(num2); + } + } + } + lookTimer = Random.Range(0.5f, 4f); + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.ai && (bool)base.body) + { + BroadNavigationSystem.Agent broadNavigationAgent = base.ai.broadNavigationAgent; + targetPosition = PickRandomNearbyReachablePosition(); + if (targetPosition.HasValue) + { + broadNavigationAgent.goalPosition = targetPosition.Value; + broadNavigationAgent.InvalidatePath(); + } + PickNewTargetLookPosition(); + aiUpdateTimer = 0.5f; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + aiUpdateTimer -= GetDeltaTime(); + if (!base.ai || !base.body) + { + return; + } + if ((bool)base.ai.skillDriverEvaluation.dominantSkillDriver) + { + outer.SetNextState(new Combat()); + } + base.ai.SetGoalPosition(targetPosition); + _ = base.bodyTransform.position; + BroadNavigationSystem.Agent broadNavigationAgent = base.ai.broadNavigationAgent; + if (aiUpdateTimer <= 0f) + { + aiUpdateTimer = BaseAIState.cvAIUpdateInterval.value; + base.ai.localNavigator.targetPosition = broadNavigationAgent.output.nextPosition ?? base.ai.localNavigator.targetPosition; + base.ai.localNavigator.Update(BaseAIState.cvAIUpdateInterval.value); + if ((bool)base.bodyInputBank) + { + bodyInputs.moveVector = base.ai.localNavigator.moveVector * 0.25f; + bodyInputs.desiredAimDirection = (targetLookPosition - base.bodyInputBank.aimOrigin).normalized; + } + lookTimer -= GetDeltaTime(); + if (lookTimer <= 0f) + { + PickNewTargetLookPosition(); + } + bool flag = false; + if (targetPosition.HasValue) + { + float sqrMagnitude = (base.body.footPosition - targetPosition.Value).sqrMagnitude; + float num = base.body.radius * base.body.radius * 4f; + flag = sqrMagnitude > num; + } + if (!flag) + { + outer.SetNextState(new LookBusy()); + } + } + } + + public override BaseAI.BodyInputs GenerateBodyInputs(in BaseAI.BodyInputs previousBodyInputs) + { + ModifyInputsForJumpIfNeccessary(ref bodyInputs); + return bodyInputs; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AI/BaseAIState.cs b/ilspy_dump/ror2_csproj/EntityStates.AI/BaseAIState.cs new file mode 100644 index 0000000..a3adc87 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AI/BaseAIState.cs @@ -0,0 +1,157 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.CharacterAI; +using RoR2.ConVar; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.AI; + +public abstract class BaseAIState : EntityState +{ + protected static FloatConVar cvAIUpdateInterval = new FloatConVar("ai_update_interval", ConVarFlags.Cheat, "0.2", "Frequency that the local navigator refreshes."); + + protected BaseAI.BodyInputs bodyInputs; + + protected bool isInJump; + + protected Vector3? jumpLockedMoveVector; + + protected CharacterMaster characterMaster { get; private set; } + + protected BaseAI ai { get; private set; } + + protected CharacterBody body { get; private set; } + + protected Transform bodyTransform { get; private set; } + + protected InputBankTest bodyInputBank { get; private set; } + + protected CharacterMotor bodyCharacterMotor { get; private set; } + + protected SkillLocator bodySkillLocator { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + characterMaster = GetComponent(); + ai = GetComponent(); + if ((bool)ai) + { + body = ai.body; + bodyTransform = ai.bodyTransform; + bodyInputBank = ai.bodyInputBank; + bodyCharacterMotor = ai.bodyCharacterMotor; + bodySkillLocator = ai.bodySkillLocator; + } + bodyInputs = default(BaseAI.BodyInputs); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + public virtual BaseAI.BodyInputs GenerateBodyInputs(in BaseAI.BodyInputs previousBodyInputs) + { + return bodyInputs; + } + + protected void ModifyInputsForJumpIfNeccessary(ref BaseAI.BodyInputs bodyInputs) + { + if (!ai) + { + return; + } + BroadNavigationSystem.AgentOutput output = ai.broadNavigationAgent.output; + bodyInputs.pressJump = false; + if (!bodyCharacterMotor) + { + return; + } + bool isGrounded = bodyCharacterMotor.isGrounded; + bool flag = isGrounded || bodyCharacterMotor.isFlying || !bodyCharacterMotor.useGravity; + if (isInJump && flag) + { + isInJump = false; + jumpLockedMoveVector = null; + } + if (isGrounded) + { + float num = Mathf.Max(output.desiredJumpVelocity, ai.localNavigator.jumpSpeed); + if (num > 0f && body.jumpPower > 0f) + { + bool num2 = output.desiredJumpVelocity >= ai.localNavigator.jumpSpeed; + num = body.jumpPower; + bodyInputs.pressJump = true; + if (num2 && output.nextPosition.HasValue) + { + Vector3 vector = output.nextPosition.Value - bodyTransform.position; + Vector3 vector2 = vector; + vector2.y = 0f; + float num3 = Trajectory.CalculateFlightDuration(0f, vector.y, num); + float walkSpeed = bodyCharacterMotor.walkSpeed; + if (num3 > 0f && walkSpeed > 0f) + { + float magnitude = vector2.magnitude; + float num4 = Mathf.Max(magnitude / num3 / bodyCharacterMotor.walkSpeed, 0f); + jumpLockedMoveVector = vector2 * (num4 / magnitude); + bodyCharacterMotor.moveDirection = jumpLockedMoveVector.Value; + } + } + isInJump = true; + } + } + if (jumpLockedMoveVector.HasValue) + { + bodyInputs.moveVector = jumpLockedMoveVector.Value; + } + } + + protected Vector3? PickRandomNearbyReachablePosition() + { + if (!ai || !body) + { + return null; + } + NodeGraph nodeGraph = SceneInfo.instance.GetNodeGraph(body.isFlying ? MapNodeGroup.GraphType.Air : MapNodeGroup.GraphType.Ground); + NodeGraphSpider nodeGraphSpider = new NodeGraphSpider(nodeGraph, (HullMask)(1 << (int)body.hullClassification)); + NodeGraph.NodeIndex nodeIndex = nodeGraph.FindClosestNode(bodyTransform.position, body.hullClassification, 50f); + nodeGraphSpider.AddNodeForNextStep(nodeIndex); + nodeGraphSpider.PerformStep(); + nodeGraphSpider.PerformStep(); + List collectedSteps = nodeGraphSpider.collectedSteps; + if (collectedSteps.Count == 0) + { + return null; + } + int index = Random.Range(0, collectedSteps.Count); + NodeGraph.NodeIndex node = collectedSteps[index].node; + if (nodeGraph.GetNodePosition(node, out var position)) + { + return position; + } + return null; + } + + protected void AimAt(ref BaseAI.BodyInputs dest, BaseAI.Target aimTarget) + { + if (aimTarget != null && aimTarget.GetBullseyePosition(out var position)) + { + dest.desiredAimDirection = (position - bodyInputBank.aimOrigin).normalized; + } + } + + protected void AimInDirection(ref BaseAI.BodyInputs dest, Vector3 aimDirection) + { + if (aimDirection != Vector3.zero) + { + dest.desiredAimDirection = aimDirection; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/Death.cs b/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/Death.cs new file mode 100644 index 0000000..6e2b6c3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/Death.cs @@ -0,0 +1,35 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.AcidLarva; + +public class Death : GenericCharacterDeath +{ + public static float deathDelay; + + public static GameObject deathEffectPrefab; + + private bool hasDied; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > deathDelay && !hasDied) + { + hasDied = true; + DestroyModel(); + EffectManager.SimpleImpactEffect(deathEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: false); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/LarvaLeap.cs b/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/LarvaLeap.cs new file mode 100644 index 0000000..e55e9d3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/LarvaLeap.cs @@ -0,0 +1,258 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.AcidLarva; + +public class LarvaLeap : BaseCharacterMain +{ + [SerializeField] + public float minimumDuration; + + [SerializeField] + public float blastRadius; + + [SerializeField] + public float blastProcCoefficient; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastForce; + + [SerializeField] + public string leapSoundString; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public GameObject blastImpactEffectPrefab; + + [SerializeField] + public GameObject blastEffectPrefab; + + [SerializeField] + public float airControl; + + [SerializeField] + public float aimVelocity; + + [SerializeField] + public float upwardVelocity; + + [SerializeField] + public float forwardVelocity; + + [SerializeField] + public float minimumY; + + [SerializeField] + public float minYVelocityForAnim; + + [SerializeField] + public float maxYVelocityForAnim; + + [SerializeField] + public float knockbackForce; + + [SerializeField] + public float maxRadiusToConfirmDetonate; + + [SerializeField] + public bool confirmDetonate; + + [SerializeField] + public GameObject spinEffectPrefab; + + [SerializeField] + public string spinEffectMuzzleString; + + [SerializeField] + public string soundLoopStartEvent; + + [SerializeField] + public string soundLoopStopEvent; + + [SerializeField] + public NetworkSoundEventDef landingSound; + + [SerializeField] + public float detonateSelfDamageFraction; + + private float previousAirControl; + + private GameObject spinEffectInstance; + + protected bool isCritAuthority; + + protected CrocoDamageTypeController crocoDamageTypeController; + + private bool detonateNextFrame; + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + protected virtual DamageTypeCombo GetBlastDamageType() + { + return DamageType.Generic; + } + + public override void OnEnter() + { + base.OnEnter(); + previousAirControl = base.characterMotor.airControl; + base.characterMotor.airControl = airControl; + Vector3 direction = GetAimRay().direction; + if (base.isAuthority) + { + base.characterBody.isSprinting = true; + direction.y = Mathf.Max(direction.y, minimumY); + Vector3 vector = direction.normalized * aimVelocity * moveSpeedStat; + Vector3 vector2 = Vector3.up * upwardVelocity; + Vector3 vector3 = new Vector3(direction.x, 0f, direction.z).normalized * forwardVelocity; + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.velocity = vector + vector2 + vector3; + isCritAuthority = RollCrit(); + } + PlayCrossfade("Gesture, Override", "LarvaLeap", 0.1f); + Util.PlaySound(leapSoundString, base.gameObject); + base.characterDirection.moveVector = direction; + spinEffectInstance = Object.Instantiate(spinEffectPrefab, FindModelChild(spinEffectMuzzleString)); + if (base.isAuthority) + { + base.characterMotor.onMovementHit += OnMovementHit; + } + Util.PlaySound(soundLoopStartEvent, base.gameObject); + } + + private void OnMovementHit(ref CharacterMotor.MovementHitInfo movementHitInfo) + { + detonateNextFrame = true; + } + + protected override void UpdateAnimationParameters() + { + base.UpdateAnimationParameters(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority || !base.characterMotor) + { + return; + } + base.characterMotor.moveDirection = base.inputBank.moveVector; + base.characterDirection.moveVector = base.characterMotor.velocity; + base.characterMotor.disableAirControlUntilCollision = base.characterMotor.velocity.y < 0f; + if (base.fixedAge >= minimumDuration && (detonateNextFrame || (base.characterMotor.Motor.GroundingStatus.IsStableOnGround && !base.characterMotor.Motor.LastGroundingStatus.IsStableOnGround))) + { + bool flag = true; + if (confirmDetonate) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(base.characterBody.teamComponent.teamIndex); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.minDistanceFilter = 0f; + bullseyeSearch.maxDistanceFilter = maxRadiusToConfirmDetonate; + bullseyeSearch.searchOrigin = base.inputBank.aimOrigin; + bullseyeSearch.searchDirection = base.inputBank.aimDirection; + bullseyeSearch.maxAngleFilter = 180f; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.RefreshCandidates(); + flag = bullseyeSearch.GetResults().FirstOrDefault(); + } + if (flag) + { + DoImpactAuthority(); + } + outer.SetNextStateToMain(); + } + } + + protected virtual void DoImpactAuthority() + { + DetonateAuthority(); + if ((bool)landingSound) + { + EffectManager.SimpleSoundEffect(landingSound.index, base.characterBody.footPosition, transmit: true); + } + base.healthComponent.TakeDamage(new DamageInfo + { + damage = base.healthComponent.fullCombinedHealth * detonateSelfDamageFraction, + attacker = base.characterBody.gameObject, + position = base.characterBody.corePosition, + damageType = DamageType.Generic + }); + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 footPosition = base.characterBody.footPosition; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = footPosition, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = isCritAuthority, + damageType = GetBlastDamageType(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = footPosition, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + protected void FireProjectile() + { + Vector3 footPosition = base.characterBody.footPosition; + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.crit = isCritAuthority; + fireProjectileInfo.force = 0f; + fireProjectileInfo.damage = damageStat; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.position = footPosition; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + + public override void OnExit() + { + Util.PlaySound(soundLoopStopEvent, base.gameObject); + if (base.isAuthority) + { + base.characterMotor.onMovementHit -= OnMovementHit; + } + base.characterMotor.airControl = previousAirControl; + base.characterBody.isSprinting = false; + if ((bool)spinEffectInstance) + { + EntityState.Destroy(spinEffectInstance); + } + PlayAnimation("Gesture, Override", EmptyStateHash); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/SpawnState.cs new file mode 100644 index 0000000..554dea8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AcidLarva/SpawnState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.AcidLarva; + +public class SpawnState : GenericCharacterSpawnState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/Chargeup.cs b/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/Chargeup.cs new file mode 100644 index 0000000..673cc55 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/Chargeup.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.AffixEarthHealer; + +public class Chargeup : BaseState +{ + private static int chargeUpAnimationStateHash = Animator.StringToHash("ChargeUp"); + + private static int chargeUpParamHash = Animator.StringToHash("ChargeUp.playbackRate"); + + public static float duration; + + public static string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + FindModelChild("ChargeUpFX").gameObject.SetActive(value: true); + PlayAnimation("Base", chargeUpAnimationStateHash, chargeUpParamHash, duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new Heal()); + } + } + + public override void OnExit() + { + FindModelChild("ChargeUpFX").gameObject.SetActive(value: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/DeathState.cs new file mode 100644 index 0000000..577865e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/DeathState.cs @@ -0,0 +1,32 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.AffixEarthHealer; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialExplosion; + + public static float duration; + + public static string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)initialExplosion) + { + EffectManager.SimpleEffect(initialExplosion, base.transform.position, base.transform.rotation, transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge > duration) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/Heal.cs b/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/Heal.cs new file mode 100644 index 0000000..b966a4d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AffixEarthHealer/Heal.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.AffixEarthHealer; + +public class Heal : BaseState +{ + public static float radius; + + public static float healCoefficient; + + public static float healOrbTravelDuration; + + public static GameObject effectPrefab; + + public override void OnEnter() + { + base.OnEnter(); + float healValue = base.characterBody.damage * healCoefficient; + if (!NetworkServer.active) + { + return; + } + List list = new List(); + SphereSearch sphereSearch = new SphereSearch(); + sphereSearch.radius = radius; + sphereSearch.origin = base.transform.position; + sphereSearch.queryTriggerInteraction = QueryTriggerInteraction.Ignore; + sphereSearch.mask = LayerIndex.entityPrecise.mask; + sphereSearch.RefreshCandidates(); + sphereSearch.FilterCandidatesByDistinctHurtBoxEntities(); + HurtBox[] hurtBoxes = sphereSearch.GetHurtBoxes(); + for (int i = 0; i < hurtBoxes.Length; i++) + { + HealthComponent item = hurtBoxes[i].healthComponent; + if (!list.Contains(item)) + { + list.Add(item); + } + } + foreach (HealthComponent item2 in list) + { + HealOrb healOrb = new HealOrb(); + healOrb.origin = base.transform.position; + healOrb.target = item2.body.mainHurtBox; + healOrb.healValue = healValue; + healOrb.overrideDuration = healOrbTravelDuration; + OrbManager.instance.AddOrb(healOrb); + } + EffectManager.SimpleEffect(effectPrefab, base.transform.position, Quaternion.identity, transmit: true); + base.characterBody.healthComponent.Suicide(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AffixVoid/SelfDestruct.cs b/ilspy_dump/ror2_csproj/EntityStates.AffixVoid/SelfDestruct.cs new file mode 100644 index 0000000..efe5555 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AffixVoid/SelfDestruct.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.AffixVoid; + +public class SelfDestruct : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade(animationLayerName, animationStateName, duration); + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChannelRain.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChannelRain.cs new file mode 100644 index 0000000..b74416f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChannelRain.cs @@ -0,0 +1,126 @@ +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class ChannelRain : BaseState +{ + private float castTimer; + + public static float baseDuration = 4f; + + public static float explosionDelay = 2f; + + public static int explosionCount = 10; + + public static float damageCoefficient; + + public static float randomRadius; + + public static float radius; + + public static GameObject delayPrefab; + + private float duration; + + private float durationBetweenCast; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + durationBetweenCast = baseDuration / (float)explosionCount / attackSpeedStat; + PlayCrossfade("Body", "ChannelRain", 0.3f); + } + + private void PlaceRain() + { + Vector3 vector = Vector3.zero; + Ray aimRay = GetAimRay(); + aimRay.origin += Random.insideUnitSphere * randomRadius; + if (Physics.Raycast(aimRay, out var hitInfo, (int)LayerIndex.world.mask)) + { + vector = hitInfo.point; + } + if (!(vector != Vector3.zero)) + { + return; + } + Transform transform = FindTargetClosest(vector, base.characterBody.GetComponent().teamIndex switch + { + TeamIndex.Monster => TeamIndex.Player, + TeamIndex.Player => TeamIndex.Monster, + _ => TeamIndex.Neutral, + }); + Vector3 vector2 = vector; + if ((bool)transform) + { + vector2 = transform.transform.position; + } + vector2 += Random.insideUnitSphere * randomRadius; + Ray ray = default(Ray); + ray.origin = vector2 + Vector3.up * randomRadius; + ray.direction = Vector3.down; + if (Physics.Raycast(ray, out hitInfo, 500f, LayerIndex.world.mask)) + { + Vector3 point = hitInfo.point; + Quaternion rotation = Util.QuaternionSafeLookRotation(hitInfo.normal); + GameObject obj = Object.Instantiate(delayPrefab, point, rotation); + DelayBlast component = obj.GetComponent(); + component.position = point; + component.baseDamage = base.characterBody.damage * damageCoefficient; + component.baseForce = 2000f; + component.bonusForce = Vector3.up * 1000f; + component.radius = radius; + component.attacker = base.gameObject; + component.inflictor = null; + component.crit = Util.CheckRoll(critStat, base.characterBody.master); + component.maxTimer = explosionDelay; + obj.GetComponent().teamIndex = TeamComponent.GetObjectTeam(component.attacker); + obj.transform.localScale = new Vector3(radius, radius, 1f); + ScaleParticleSystemDuration component2 = obj.GetComponent(); + if ((bool)component2) + { + component2.newDuration = explosionDelay; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + castTimer += GetDeltaTime(); + if (castTimer >= durationBetweenCast) + { + PlaceRain(); + castTimer -= durationBetweenCast; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new EndRain()); + } + } + + private Transform FindTargetClosest(Vector3 point, TeamIndex enemyTeam) + { + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(enemyTeam); + float num = 99999f; + Transform result = null; + for (int i = 0; i < teamMembers.Count; i++) + { + float num2 = Vector3.SqrMagnitude(teamMembers[i].transform.position - point); + if (num2 < num) + { + num = num2; + result = teamMembers[i].transform; + } + } + return result; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeBomb.cs new file mode 100644 index 0000000..1806a3d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeBomb.cs @@ -0,0 +1,189 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class ChargeBomb : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject effectPrefab; + + public static GameObject delayPrefab; + + public static float radius = 10f; + + public static float damageCoefficient = 1f; + + private float duration; + + private GameObject chargeEffectLeft; + + private GameObject chargeEffectRight; + + private Vector3 startLine = Vector3.zero; + + private Vector3 endLine = Vector3.zero; + + private bool hasFired; + + private EffectManagerHelper _emh_chargeEffectLeft; + + private EffectManagerHelper _emh_chargeEffectRight; + + private static int chargeBombAnimStateHash = Animator.StringToHash("ChargeBomb"); + + private static int chargeBombParamHas = Animator.StringToHash("ChargeBomb.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffectLeft = null; + chargeEffectRight = null; + startLine = Vector3.zero; + endLine = Vector3.zero; + hasFired = false; + _emh_chargeEffectLeft = null; + _emh_chargeEffectRight = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture", chargeBombAnimStateHash, chargeBombParamHas, duration); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component && (bool)effectPrefab) + { + Transform transform = component.FindChild("MuzzleLeft"); + Transform transform2 = component.FindChild("MuzzleRight"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffectLeft = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectLeft = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffectLeft = _emh_chargeEffectLeft.gameObject; + } + chargeEffectLeft.transform.parent = transform; + } + if ((bool)transform2) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffectRight = Object.Instantiate(effectPrefab, transform2.position, transform2.rotation); + } + else + { + _emh_chargeEffectRight = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform2.position, transform2.rotation); + chargeEffectRight = _emh_chargeEffectRight.gameObject; + } + chargeEffectRight.transform.parent = transform2; + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + if (Physics.Raycast(GetAimRay(), out var hitInfo, (int)LayerIndex.world.mask)) + { + startLine = hitInfo.point; + } + } + + public override void OnExit() + { + base.OnExit(); + if (_emh_chargeEffectLeft != null && _emh_chargeEffectLeft.OwningPool != null) + { + _emh_chargeEffectLeft.OwningPool.ReturnObject(_emh_chargeEffectLeft); + } + else + { + EntityState.Destroy(chargeEffectLeft); + } + chargeEffectLeft = null; + _emh_chargeEffectLeft = null; + if (_emh_chargeEffectRight != null && _emh_chargeEffectRight.OwningPool != null) + { + _emh_chargeEffectRight.OwningPool.ReturnObject(_emh_chargeEffectRight); + } + else + { + EntityState.Destroy(chargeEffectRight); + } + chargeEffectRight = null; + _emh_chargeEffectRight = null; + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float num = 0f; + if (base.fixedAge >= num && !hasFired) + { + hasFired = true; + Ray aimRay = GetAimRay(); + if (Physics.Raycast(aimRay, out var hitInfo, (int)LayerIndex.world.mask)) + { + endLine = hitInfo.point; + } + Vector3 normalized = (endLine - startLine).normalized; + normalized.y = 0f; + normalized.Normalize(); + for (int i = 0; i < 1; i++) + { + Vector3 vector = endLine; + Ray ray = default(Ray); + ray.origin = aimRay.origin; + ray.direction = vector - aimRay.origin; + Debug.DrawLine(ray.origin, vector, Color.red, 5f); + if (Physics.Raycast(ray, out hitInfo, 500f, LayerIndex.world.mask)) + { + Vector3 point = hitInfo.point; + Quaternion rotation = Util.QuaternionSafeLookRotation(hitInfo.normal); + GameObject obj = Object.Instantiate(delayPrefab, point, rotation); + DelayBlast component = obj.GetComponent(); + component.position = point; + component.baseDamage = base.characterBody.damage * damageCoefficient; + component.baseForce = 2000f; + component.bonusForce = Vector3.up * 1000f; + component.radius = radius; + component.attacker = base.gameObject; + component.inflictor = null; + component.crit = Util.CheckRoll(critStat, base.characterBody.master); + component.maxTimer = duration; + obj.GetComponent().teamIndex = TeamComponent.GetObjectTeam(component.attacker); + obj.transform.localScale = new Vector3(radius, radius, 1f); + ScaleParticleSystemDuration component2 = obj.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new FireBomb()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeRHCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeRHCannon.cs new file mode 100644 index 0000000..04ef484 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeRHCannon.cs @@ -0,0 +1,95 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class ChargeRHCannon : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject effectPrefab; + + private float duration; + + private GameObject chargeEffectLeft; + + private GameObject chargeEffectRight; + + private EffectManagerHelper _emh_chargeEffectRight; + + private static int chargeRHCannonHash = Animator.StringToHash("ChargeRHCannon"); + + private static int chargeRHCannonPlaybackHash = Animator.StringToHash("ChargeRHCannon.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffectLeft = null; + chargeEffectRight = null; + _emh_chargeEffectRight = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayAnimation("Gesture", chargeRHCannonHash, chargeRHCannonPlaybackHash, duration); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component && (bool)effectPrefab) + { + Transform transform = component.FindChild("MuzzleRight"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffectRight = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectRight = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffectRight = _emh_chargeEffectRight.gameObject; + } + chargeEffectRight.transform.parent = transform; + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + base.OnExit(); + if (_emh_chargeEffectRight != null && _emh_chargeEffectRight.OwningPool != null) + { + _emh_chargeEffectRight.OwningPool.ReturnObject(_emh_chargeEffectRight); + } + else + { + EntityState.Destroy(chargeEffectRight); + } + chargeEffectRight = null; + _emh_chargeEffectRight = null; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireRHCannon nextState = new FireRHCannon(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeRain.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeRain.cs new file mode 100644 index 0000000..2ac22ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/ChargeRain.cs @@ -0,0 +1,62 @@ +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class ChargeRain : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject effectPrefab; + + public static GameObject delayPrefab; + + private float duration; + + private static int chargeRainStateHash = Animator.StringToHash("ChargeRain"); + + private static int chargeRainplaybackRateParamHash = Animator.StringToHash("ChargeRain.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + PlayAnimation("Body", chargeRainStateHash, chargeRainplaybackRateParamHash, duration); + if (Physics.Raycast(base.transform.position, Vector3.down, out var hitInfo, 999f, LayerIndex.world.mask)) + { + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNode(hitInfo.point, HullClassification.BeetleQueen); + groundNodes.GetNodePosition(nodeIndex, out var position); + base.transform.position = position + Vector3.up * 2f; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new ChannelRain()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/EndRain.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/EndRain.cs new file mode 100644 index 0000000..d8ba8dd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/EndRain.cs @@ -0,0 +1,59 @@ +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class EndRain : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject effectPrefab; + + public static GameObject delayPrefab; + + private float duration; + + private static int endRainHash = Animator.StringToHash("EndRain"); + + private static int endRainParamHash = Animator.StringToHash("EndRain.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + PlayAnimation("Body", endRainHash, endRainParamHash, duration); + NodeGraph airNodes = SceneInfo.instance.airNodes; + NodeGraph.NodeIndex nodeIndex = airNodes.FindClosestNode(base.transform.position, base.characterBody.hullClassification); + airNodes.GetNodePosition(nodeIndex, out var position); + base.transform.position = position; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/Enrage.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/Enrage.cs new file mode 100644 index 0000000..ae618c5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/Enrage.cs @@ -0,0 +1,89 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.AncientWispMonster; + +public class Enrage : BaseState +{ + public static float baseDuration = 3.5f; + + public static GameObject enragePrefab; + + private Animator modelAnimator; + + private float duration; + + private bool hasCastBuff; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayCrossfade("Gesture", "Enrage", "Enrage.playbackRate", duration, 0.2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("Enrage.activate") > 0.5f && !hasCastBuff) + { + EffectData effectData = new EffectData(); + effectData.origin = base.transform.position; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(enragePrefab, effectData, transmit: true); + hasCastBuff = true; + base.characterBody.AddBuff(JunkContent.Buffs.EnrageAncientWisp); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private static void PullEnemies(Vector3 position, Vector3 direction, float coneAngle, float maxDistance, float force, TeamIndex excludedTeam) + { + float num = Mathf.Cos(coneAngle * 0.5f * (MathF.PI / 180f)); + HGPhysics.OverlapSphere(out var colliders, position, maxDistance); + foreach (Collider collider in colliders) + { + Vector3 position2 = collider.transform.position; + Vector3 normalized = (position - position2).normalized; + if (!(Vector3.Dot(-normalized, direction) >= num)) + { + continue; + } + TeamIndex teamIndex = TeamIndex.Neutral; + TeamComponent component = collider.GetComponent(); + if (!component) + { + continue; + } + teamIndex = component.teamIndex; + if (teamIndex != excludedTeam) + { + CharacterMotor component2 = collider.GetComponent(); + if ((bool)component2) + { + component2.ApplyForce(normalized * force); + } + Rigidbody component3 = collider.GetComponent(); + if ((bool)component3) + { + component3.AddForce(normalized * force, ForceMode.Impulse); + } + } + } + HGPhysics.ReturnResults(colliders); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/FireBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/FireBomb.cs new file mode 100644 index 0000000..d89d8f0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/FireBomb.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class FireBomb : BaseState +{ + public static float baseDuration = 4f; + + private float duration; + + private static int fireBombHash = Animator.StringToHash("FireBomb"); + + private static int fireBombParamHash = Animator.StringToHash("FireBomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture", fireBombHash, fireBombParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/FireRHCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/FireRHCannon.cs new file mode 100644 index 0000000..66df2b0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/FireRHCannon.cs @@ -0,0 +1,93 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.AncientWispMonster; + +public class FireRHCannon : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float baseDuration = 2f; + + public static float baseDurationBetweenShots = 0.5f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static int bulletCount; + + private float duration; + + private float durationBetweenShots; + + public int bulletCountCurrent = 1; + + private static int fireRHCannonHash = Animator.StringToHash("FireRHCannon"); + + private static int fireRHCannonParamHash = Animator.StringToHash("FireRHCannon.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + string text = "MuzzleRight"; + duration = baseDuration / attackSpeedStat; + durationBetweenShots = baseDurationBetweenShots / attackSpeedStat; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, text, transmit: false); + } + PlayAnimation("Gesture", fireRHCannonHash, fireRHCannonParamHash, duration); + if (!base.isAuthority || !base.modelLocator || !base.modelLocator.modelTransform) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild(text); + if ((bool)transform) + { + Vector3 forward = aimRay.direction; + if (Physics.Raycast(aimRay, out var hitInfo, (int)LayerIndex.world.mask)) + { + forward = hitInfo.point - transform.position; + } + ProjectileManager.instance.FireProjectile(projectilePrefab, transform.position, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (bulletCountCurrent == bulletCount && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + else if (bulletCountCurrent < bulletCount && base.fixedAge >= durationBetweenShots) + { + FireRHCannon fireRHCannon = new FireRHCannon(); + fireRHCannon.bulletCountCurrent = bulletCountCurrent + 1; + outer.SetNextState(fireRHCannon); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/Throw.cs b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/Throw.cs new file mode 100644 index 0000000..dd467f7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AncientWispMonster/Throw.cs @@ -0,0 +1,128 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.AncientWispMonster; + +public class Throw : BaseState +{ + public static float baseDuration = 3.5f; + + public static float returnToIdlePercentage; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + public static GameObject projectilePrefab; + + public static GameObject swingEffectPrefab; + + private Transform rightMuzzleTransform; + + private Animator modelAnimator; + + private float duration; + + private bool hasSwung; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + rightMuzzleTransform = component.FindChild("MuzzleRight"); + } + } + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Gesture"); + if (modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("Throw1")) + { + PlayCrossfade("Gesture", "Throw2", "Throw.playbackRate", duration / (1f - returnToIdlePercentage), 0.2f); + } + else + { + PlayCrossfade("Gesture", "Throw1", "Throw.playbackRate", duration / (1f - returnToIdlePercentage), 0.2f); + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("Throw.activate") > 0f && !hasSwung) + { + Ray aimRay = GetAimRay(); + Vector3 forward = aimRay.direction; + if (Physics.Raycast(aimRay, out var hitInfo, (int)LayerIndex.world.mask)) + { + forward = hitInfo.point - rightMuzzleTransform.position; + } + ProjectileManager.instance.FireProjectile(projectilePrefab, rightMuzzleTransform.position, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, forceMagnitude, Util.CheckRoll(critStat, base.characterBody.master)); + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, "RightSwingCenter", transmit: true); + hasSwung = true; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private static void PullEnemies(Vector3 position, Vector3 direction, float coneAngle, float maxDistance, float force, TeamIndex excludedTeam) + { + float num = Mathf.Cos(coneAngle * 0.5f * (MathF.PI / 180f)); + Collider[] colliders; + int num2 = HGPhysics.OverlapSphere(out colliders, position, maxDistance); + for (int i = 0; i < num2; i++) + { + Collider collider = colliders[i]; + Vector3 position2 = collider.transform.position; + Vector3 normalized = (position - position2).normalized; + if (!(Vector3.Dot(-normalized, direction) >= num)) + { + continue; + } + TeamIndex teamIndex = TeamIndex.Neutral; + TeamComponent component = collider.GetComponent(); + if (!component) + { + continue; + } + teamIndex = component.teamIndex; + if (teamIndex != excludedTeam) + { + CharacterMotor component2 = collider.GetComponent(); + if ((bool)component2) + { + component2.ApplyForce(normalized * force); + } + Rigidbody component3 = collider.GetComponent(); + if ((bool)component3) + { + component3.AddForce(normalized * force, ForceMode.Impulse); + } + } + } + HGPhysics.ReturnResults(colliders); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/ChargeCannons.cs b/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/ChargeCannons.cs new file mode 100644 index 0000000..f3a8f84 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/ChargeCannons.cs @@ -0,0 +1,16 @@ +using EntityStates.GreaterWispMonster; + +namespace EntityStates.ArchWispMonster; + +public class ChargeCannons : EntityStates.GreaterWispMonster.ChargeCannons +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireCannons nextState = new FireCannons(); + outer.SetNextState(nextState); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/DeathState.cs new file mode 100644 index 0000000..9241a5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/DeathState.cs @@ -0,0 +1,7 @@ +using EntityStates.GreaterWispMonster; + +namespace EntityStates.ArchWispMonster; + +public class DeathState : EntityStates.GreaterWispMonster.DeathState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/FireCannons.cs b/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/FireCannons.cs new file mode 100644 index 0000000..4912bac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArchWispMonster/FireCannons.cs @@ -0,0 +1,7 @@ +using EntityStates.GreaterWispMonster; + +namespace EntityStates.ArchWispMonster; + +public class FireCannons : EntityStates.GreaterWispMonster.FireCannons +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/ArtifactShellBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/ArtifactShellBaseState.cs new file mode 100644 index 0000000..dc632bb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/ArtifactShellBaseState.cs @@ -0,0 +1,114 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +namespace EntityStates.ArtifactShell; + +public class ArtifactShellBaseState : BaseState +{ + protected Light light; + + private string stopLoopSound; + + protected PurchaseInteraction purchaseInteraction { get; private set; } + + protected virtual CostTypeIndex interactionCostType => CostTypeIndex.None; + + protected virtual bool interactionAvailable => false; + + protected virtual int interactionCost => 0; + + protected ParticleSystem rayParticleSystem { get; private set; } + + protected PostProcessVolume postProcessVolume { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction = GetComponent(); + if ((object)purchaseInteraction != null) + { + purchaseInteraction.costType = interactionCostType; + purchaseInteraction.Networkcost = interactionCost; + purchaseInteraction.Networkavailable = interactionAvailable; + purchaseInteraction.onPurchase.AddListener(DoOnPurchase); + } + rayParticleSystem = FindModelChild("RayParticles")?.GetComponent(); + postProcessVolume = FindModelChild("PP")?.GetComponent(); + light = FindModelChild("Light").GetComponent(); + CalcLoopSounds(base.healthComponent.combinedHealthFraction, out var startLoopSound, out stopLoopSound); + Util.PlaySound(startLoopSound, base.gameObject); + } + + private static void CalcLoopSounds(float currentHealthFraction, out string startLoopSound, out string stopLoopSound) + { + startLoopSound = null; + stopLoopSound = null; + float num = 0.05f; + if (currentHealthFraction > 0.75f + num) + { + startLoopSound = "Play_artifactBoss_loop_level1"; + stopLoopSound = "Stop_artifactBoss_loop_level1"; + } + else if (currentHealthFraction > 0.25f + num) + { + startLoopSound = "Play_artifactBoss_loop_level2"; + stopLoopSound = "Stop_artifactBoss_loop_level2"; + } + else if (currentHealthFraction > 0f + num) + { + startLoopSound = "Play_artifactBoss_loop_level2"; + stopLoopSound = "Stop_artifactBoss_loop_level2"; + } + } + + public override void OnExit() + { + Util.PlaySound(stopLoopSound, base.gameObject); + if ((object)purchaseInteraction != null) + { + purchaseInteraction.onPurchase.RemoveListener(DoOnPurchase); + purchaseInteraction = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + UpdateVisuals(); + } + + private void DoOnPurchase(Interactor activator) + { + OnPurchase(activator); + } + + protected virtual void OnPurchase(Interactor activator) + { + } + + protected void UpdateVisuals() + { + float num = 1f - base.healthComponent.combinedHealthFraction; + if ((bool)rayParticleSystem) + { + ParticleSystem.EmissionModule emission = rayParticleSystem.emission; + emission.rateOverTime = Util.Remap(num, 0f, 1f, 0f, 10f); + ParticleSystem.MainModule main = rayParticleSystem.main; + main.simulationSpeed = Util.Remap(num, 0f, 1f, 1f, 5f); + } + if ((bool)postProcessVolume) + { + if (!Mathf.Approximately(postProcessVolume.weight, num)) + { + PostProcessVolume.DispatchVolumeSettingsChangedEvent(); + } + postProcessVolume.weight = num; + } + if ((bool)light) + { + light.range = 10f + num * 150f; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/Death.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/Death.cs new file mode 100644 index 0000000..3369cb3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/Death.cs @@ -0,0 +1,30 @@ +using RoR2; + +namespace EntityStates.ArtifactShell; + +public class Death : ArtifactShellBaseState +{ + public static float duration; + + protected override bool interactionAvailable => false; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(GetComponent().deathSound, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + EntityState.Destroy(base.gameObject); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/FireSolarFlares.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/FireSolarFlares.cs new file mode 100644 index 0000000..e4318e9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/FireSolarFlares.cs @@ -0,0 +1,89 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ArtifactShell; + +public class FireSolarFlares : BaseState +{ + public static GameObject projectilePrefab; + + public static int minimumProjectileCount; + + public static int maximumProjectileCount; + + public static float arc; + + public static float baseDuration; + + public static float radius; + + public static float projectileDamageCoefficient; + + public static float projectileForce; + + public static float projectileFuse; + + public static float projectileSpeed; + + private float duration; + + private int projectileCount; + + private int projectilesFired; + + private Quaternion currentRotation; + + private Quaternion deltaRotation; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.healthComponent) + { + projectileCount = (int)Util.Remap(base.healthComponent.combinedHealthFraction, 0f, 1f, maximumProjectileCount, minimumProjectileCount); + } + if (NetworkServer.active) + { + Vector3 aimDirection = base.inputBank.aimDirection; + currentRotation = Quaternion.LookRotation(aimDirection); + _ = Run.FixedTimeStamp.now.t * 2f % 1f; + Vector3 rhs = currentRotation * Vector3.forward; + Vector3 lhs = currentRotation * Vector3.right; + _ = currentRotation * Vector3.up; + deltaRotation = Quaternion.AngleAxis(arc / (float)projectileCount, Vector3.Cross(lhs, rhs)); + } + duration = baseDuration / attackSpeedStat; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + float num = duration / (float)projectileCount; + if (base.fixedAge >= (float)projectilesFired * num) + { + projectilesFired++; + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.position = base.transform.position + currentRotation * Vector3.forward * radius; + fireProjectileInfo.rotation = currentRotation; + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.fuseOverride = projectileFuse; + fireProjectileInfo.useFuseOverride = true; + fireProjectileInfo.speedOverride = projectileSpeed; + fireProjectileInfo.useSpeedOverride = true; + fireProjectileInfo.damage = damageStat * projectileDamageCoefficient; + fireProjectileInfo.force = projectileForce; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + currentRotation *= deltaRotation; + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/Hurt.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/Hurt.cs new file mode 100644 index 0000000..71187a4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/Hurt.cs @@ -0,0 +1,69 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ArtifactShell; + +public class Hurt : ArtifactShellBaseState +{ + public static float baseDuration = 2f; + + public static float blastRadius = 50f; + + public static float knockbackForce = 5000f; + + public static float knockbackLiftForce = 2000f; + + public static float blastOriginOffset = -10f; + + public static GameObject novaEffectPrefab; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + Vector3 position = base.transform.position; + if (NetworkServer.active) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.position = position; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damage = Mathf.Ceil(base.healthComponent.fullCombinedHealth * 0.25f); + damageInfo.damageType = DamageType.BypassArmor | DamageType.Silent; + damageInfo.procCoefficient = 0f; + base.healthComponent.TakeDamage(damageInfo); + BlastAttack blastAttack = new BlastAttack(); + blastAttack.position = position + blastOriginOffset * Vector3.up; + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.baseDamage = 0f; + blastAttack.baseForce = knockbackForce; + blastAttack.bonusForce = Vector3.up * knockbackLiftForce; + blastAttack.falloffModel = BlastAttack.FalloffModel.Linear; + blastAttack.radius = blastRadius; + blastAttack.procCoefficient = 0f; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.Fire(); + ArtifactTrialMissionController.RemoveAllMissionKeys(); + } + EffectData effectData = new EffectData + { + origin = position, + scale = blastRadius + }; + EffectManager.SpawnEffect(novaEffectPrefab, effectData, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextState(new WaitForKey()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/StartHurt.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/StartHurt.cs new file mode 100644 index 0000000..c2c7232 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/StartHurt.cs @@ -0,0 +1,29 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.ArtifactShell; + +public class StartHurt : ArtifactShellBaseState +{ + public static float baseDuration = 0.25f; + + public static string firstHurtSound; + + public override void OnEnter() + { + base.OnEnter(); + if (base.healthComponent.combinedHealthFraction >= 1f) + { + Util.PlaySound(firstHurtSound, base.gameObject); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= baseDuration) + { + outer.SetNextState(new Hurt()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/WaitForIntro.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/WaitForIntro.cs new file mode 100644 index 0000000..fde1fa5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/WaitForIntro.cs @@ -0,0 +1,27 @@ +using UnityEngine.Networking; + +namespace EntityStates.ArtifactShell; + +public class WaitForIntro : ArtifactShellBaseState +{ + public static float baseDuration = 10f; + + private float duration; + + protected override bool interactionAvailable => false; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextState(new WaitForKey()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/WaitForKey.cs b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/WaitForKey.cs new file mode 100644 index 0000000..cb968bd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ArtifactShell/WaitForKey.cs @@ -0,0 +1,23 @@ +using RoR2; + +namespace EntityStates.ArtifactShell; + +public class WaitForKey : ArtifactShellBaseState +{ + protected override CostTypeIndex interactionCostType => CostTypeIndex.ArtifactShellKillerItem; + + protected override int interactionCost => 1; + + protected override bool interactionAvailable => true; + + public override void OnEnter() + { + base.OnEnter(); + } + + protected override void OnPurchase(Interactor activator) + { + base.OnPurchase(activator); + outer.SetInterruptState(new StartHurt(), InterruptPriority.Pain); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin.Weapon/SlashCombo.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin.Weapon/SlashCombo.cs new file mode 100644 index 0000000..4578cbd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin.Weapon/SlashCombo.cs @@ -0,0 +1,146 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Assassin.Weapon; + +public class SlashCombo : BaseState +{ + public enum SlashComboPermutation + { + Slash1, + Slash2, + Final + } + + public static float baseDuration = 3.5f; + + public static float mecanimDurationCoefficient; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float selfForceMagnitude; + + public static float radius = 3f; + + public static GameObject hitEffectPrefab; + + public static GameObject swingEffectPrefab; + + public static string attackString; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private bool hasSlashed; + + public SlashComboPermutation slashComboPermutation; + + private static int SlashP1Hash = Animator.StringToHash("SlashP1"); + + private static int SlashP2Hash = Animator.StringToHash("SlashP2"); + + private static int SlashP3Hash = Animator.StringToHash("SlashP3"); + + private static int SlashComboParamHash = Animator.StringToHash("SlashCombo.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + Util.PlaySound(attackString, base.gameObject); + string hitboxGroupName = ""; + int animationStateHash = -1; + switch (slashComboPermutation) + { + case SlashComboPermutation.Slash1: + hitboxGroupName = "DaggerLeft"; + animationStateHash = SlashP1Hash; + break; + case SlashComboPermutation.Slash2: + hitboxGroupName = "DaggerLeft"; + animationStateHash = SlashP2Hash; + break; + case SlashComboPermutation.Final: + hitboxGroupName = "DaggerLeft"; + animationStateHash = SlashP3Hash; + break; + } + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == hitboxGroupName); + } + if ((bool)modelAnimator) + { + PlayAnimation("Gesture, Override", animationStateHash, SlashComboParamHash, duration * mecanimDurationCoefficient); + PlayAnimation("Gesture, Additive", animationStateHash, SlashComboParamHash, duration * mecanimDurationCoefficient); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("SlashCombo.hitBoxActive") > 0.1f) + { + if (!hasSlashed) + { + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, "SwingCenter", transmit: true); + HealthComponent healthComponent = base.characterBody.healthComponent; + CharacterDirection component = base.characterBody.GetComponent(); + if ((bool)healthComponent) + { + healthComponent.TakeDamageForce(selfForceMagnitude * component.forward, alwaysApply: true); + } + hasSlashed = true; + } + attack.forceVector = base.transform.forward * forceMagnitude; + attack.Fire(); + } + if (!(base.fixedAge >= duration) || !base.isAuthority) + { + return; + } + if ((bool)base.inputBank && base.inputBank.skill1.down) + { + SlashCombo slashCombo = new SlashCombo(); + switch (slashComboPermutation) + { + case SlashComboPermutation.Slash1: + slashCombo.slashComboPermutation = SlashComboPermutation.Slash2; + break; + case SlashComboPermutation.Slash2: + slashCombo.slashComboPermutation = SlashComboPermutation.Slash1; + break; + } + outer.SetNextState(slashCombo); + } + else + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin2/ChargeDash.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/ChargeDash.cs new file mode 100644 index 0000000..48dc3f6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/ChargeDash.cs @@ -0,0 +1,70 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Assassin2; + +public class ChargeDash : BaseState +{ + public static float baseDuration = 1.5f; + + public static string enterSoundString; + + private Animator modelAnimator; + + private float duration; + + private int slashCount; + + private Transform modelTransform; + + private Vector3 oldVelocity; + + private bool dashComplete; + + private static int PreAttackStateHash = Animator.StringToHash("PreAttack"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + modelTransform = GetModelTransform(); + AimAnimator component = modelTransform.GetComponent(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)component) + { + component.enabled = true; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", PreAttackStateHash); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration && base.isAuthority) + { + outer.SetNextState(new DashStrike()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin2/DashStrike.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/DashStrike.cs new file mode 100644 index 0000000..925937d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/DashStrike.cs @@ -0,0 +1,173 @@ +using System; +using RoR2; +using RoR2.CharacterAI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Assassin2; + +public class DashStrike : BaseState +{ + public static float dashDuration = 1f; + + public static float slashDuration = 1.667f; + + public static float damageCoefficient = 4f; + + public static float procCoefficient; + + public static float selfForce; + + public static float forceMagnitude = 16f; + + public static float maxDashSpeedCoefficient = 4f; + + public static float maxSlashDistance = 20f; + + public static GameObject hitEffectPrefab; + + public static GameObject swipeEffectPrefab; + + public static string enterSoundString; + + public static string slashSoundString; + + private Vector3 targetMoveVector; + + private Vector3 targetMoveVectorVelocity; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private int slashCount; + + private Transform modelTransform; + + private bool dashComplete; + + private int handParamHash; + + private int swordParamHash; + + private float calculatedDashSpeed; + + private bool startedSlash; + + private static int DashStateHash = Animator.StringToHash("Dash"); + + private static int SwordStrikeStateHash = Animator.StringToHash("SwordStrike"); + + private static int forwardSpeedParamHash = Animator.StringToHash("forwardSpeed"); + + public override void OnEnter() + { + base.OnEnter(); + duration = (dashDuration + slashDuration) / attackSpeedStat; + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + base.characterMotor.velocity = Vector3.zero; + float sqrMagnitude = (base.characterBody.master.GetComponent().currentEnemy.characterBody.corePosition - base.characterBody.corePosition).sqrMagnitude; + calculatedDashSpeed = Util.Remap(sqrMagnitude, 0f, maxSlashDistance * maxSlashDistance, 0f, maxDashSpeedCoefficient); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + attack.procCoefficient = procCoefficient; + attack.damageType = DamageType.Generic; + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", DashStateHash); + handParamHash = Animator.StringToHash("HandStrike"); + swordParamHash = Animator.StringToHash("SwordStrike"); + } + } + + public override void OnExit() + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + base.OnExit(); + } + + private void HandleSlash(int animatorParamHash, string muzzleName, string hitBoxGroupName) + { + bool flag = false; + if (modelAnimator.GetFloat(animatorParamHash) > 0.1f) + { + if (!startedSlash) + { + Util.PlaySound(slashSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(swipeEffectPrefab, base.gameObject, muzzleName, transmit: true); + startedSlash = true; + } + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == hitBoxGroupName); + } + if ((bool)base.healthComponent) + { + base.healthComponent.TakeDamageForce(base.characterDirection.forward * selfForce, alwaysApply: true); + } + attack.ResetIgnoredHealthComponents(); + if ((bool)base.characterDirection) + { + attack.forceVector = base.characterDirection.forward * forceMagnitude; + } + flag = attack.Fire(); + } + else if (startedSlash || flag) + { + slashCount++; + startedSlash = false; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!dashComplete) + { + targetMoveVector = Vector3.ProjectOnPlane(Vector3.SmoothDamp(targetMoveVector, base.inputBank.aimDirection, ref targetMoveVectorVelocity, 0f, 0f), Vector3.up).normalized; + base.characterDirection.moveVector = targetMoveVector; + Vector3 forward = base.characterDirection.forward; + float value = moveSpeedStat * calculatedDashSpeed; + base.characterMotor.moveDirection = forward * calculatedDashSpeed; + modelAnimator.SetFloat(forwardSpeedParamHash, value); + } + if (NetworkServer.active) + { + if (base.fixedAge > dashDuration && !dashComplete) + { + PlayAnimation("Gesture", SwordStrikeStateHash); + dashComplete = true; + } + if ((bool)modelAnimator) + { + switch (slashCount) + { + case 0: + HandleSlash(handParamHash, "ShurikenTag", "ShurikenHitbox"); + break; + case 1: + HandleSlash(swordParamHash, "Sword", "SwordHitbox"); + break; + } + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin2/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/DeathState.cs new file mode 100644 index 0000000..133e028 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/DeathState.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Assassin2; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathEffectPrefab; + + public static float duration = 1.333f; + + private float stopwatch; + + private Animator animator; + + private bool hasPlayedDeathEffect; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)animator) + { + stopwatch += GetDeltaTime(); + if (!hasPlayedDeathEffect && animator.GetFloat("DeathEffect") > 0.5f) + { + hasPlayedDeathEffect = true; + EffectData effectData = new EffectData(); + effectData.origin = base.transform.position; + EffectManager.SpawnEffect(deathEffectPrefab, effectData, transmit: false); + } + if (stopwatch >= duration) + { + DestroyModel(); + EntityState.Destroy(base.gameObject); + } + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin2/Hide.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/Hide.cs new file mode 100644 index 0000000..a8e2aa9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/Hide.cs @@ -0,0 +1,168 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Assassin2; + +public class Hide : BaseState +{ + private Transform modelTransform; + + public static GameObject hideEfffectPrefab; + + public static GameObject smokeEffectPrefab; + + public static Material destealthMaterial; + + private float stopwatch; + + private Vector3 blinkDestination = Vector3.zero; + + private Vector3 blinkStart = Vector3.zero; + + [Tooltip("the length of time to stay hidden")] + public static float hiddenDuration = 5f; + + [Tooltip("the entire duration of the hidden state (hidden time + time after)")] + public static float fullDuration = 10f; + + public static string beginSoundString; + + public static string endSoundString; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private bool hidden; + + private GameObject smokeEffectInstance; + + private static int DisappearStateHash = Animator.StringToHash("Disappear"); + + private static int AppearStateHash = Animator.StringToHash("Appear"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + if ((bool)smokeEffectPrefab) + { + Transform transform = modelTransform; + if ((bool)transform) + { + smokeEffectInstance = Object.Instantiate(smokeEffectPrefab, transform); + ScaleParticleSystemDuration component = smokeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = component.initialDuration; + } + } + } + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + PlayAnimation("Gesture", DisappearStateHash); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Cloak); + } + CreateHiddenEffect(Util.GetCorePosition(base.gameObject)); + if ((bool)base.healthComponent) + { + base.healthComponent.dontShowHealthbar = true; + } + hidden = true; + } + + private void CreateHiddenEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.origin = origin; + EffectManager.SpawnEffect(hideEfffectPrefab, effectData, transmit: false); + } + + private void SetPosition(Vector3 newPosition) + { + if ((bool)base.characterMotor) + { + base.characterMotor.Motor.SetPositionAndRotation(newPosition, Quaternion.identity); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= hiddenDuration && hidden) + { + Reveal(); + } + if (base.isAuthority && stopwatch > fullDuration) + { + outer.SetNextStateToMain(); + } + } + + private void Reveal() + { + Util.PlaySound(endSoundString, base.gameObject); + CreateHiddenEffect(Util.GetCorePosition(base.gameObject)); + if ((bool)modelTransform && (bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(animator.gameObject); + temporaryOverlayInstance.duration = 1f; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = animator.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = true; + } + PlayAnimation("Gesture", AppearStateHash); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Cloak); + } + if ((bool)base.healthComponent) + { + base.healthComponent.dontShowHealthbar = false; + } + if ((bool)smokeEffectInstance) + { + EntityState.Destroy(smokeEffectInstance); + } + hidden = false; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin2/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/SpawnState.cs new file mode 100644 index 0000000..6a34d5a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/SpawnState.cs @@ -0,0 +1,45 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Assassin2; + +public class SpawnState : BaseState +{ + private float stopwatch; + + public static float animDuration = 1.5f; + + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "Base", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Assassin2/ThrowShuriken.cs b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/ThrowShuriken.cs new file mode 100644 index 0000000..d18358d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Assassin2/ThrowShuriken.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Assassin2; + +public class ThrowShuriken : GenericProjectileBaseState +{ + public static string attackString; + + private Transform muzzleTransform; + + private static int ThrowShurikenStateHash = Animator.StringToHash("ThrowShuriken"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture", ThrowShurikenStateHash); + Util.PlaySound(attackString, base.gameObject); + GetAimRay(); + string text = "ShurikenTag"; + muzzleTransform = FindModelChild(text); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, text, transmit: false); + } + if (base.isAuthority) + { + FireProjectile(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartActivationState.cs b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartActivationState.cs new file mode 100644 index 0000000..03e0053 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartActivationState.cs @@ -0,0 +1,123 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.AurelioniteHeart; + +public class AurelioniteHeartActivationState : AurelioniteHeartEntityState +{ + public static float expGrantingDuration = 3f; + + [SerializeField] + public static float itemGrantingDuration = 10f; + + [SerializeField] + public ItemTier rewardDisplayTier; + + [SerializeField] + [Tooltip("The prefab to use for the reward pickup.")] + public GameObject rewardPickupPrefab; + + [SerializeField] + public Vector3 rewardOffset; + + [SerializeField] + public string falseSonSurvivorAchievement; + + [SerializeField] + public ItemDef halcyonSeed; + + [SerializeField] + public int rewardOptionCount = 1; + + [SerializeField] + public PickupDropTable rewardDropTable; + + public bool rewardGiven; + + public override void OnEnter() + { + base.OnEnter(); + rewardGiven = false; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!heartController.activated || !(base.fixedAge >= expGrantingDuration)) + { + return; + } + int participatingPlayerCount = Run.instance.participatingPlayerCount; + if (base.gameObject == null || rewardDropTable == null || participatingPlayerCount == 0) + { + return; + } + if (participatingPlayerCount > 0 && (bool)base.gameObject && (bool)rewardDropTable && !rewardGiven) + { + rewardGiven = true; + int num = participatingPlayerCount; + float angle = 360f / (float)num; + Vector3 vector = Quaternion.AngleAxis(Random.Range(0, 360), Vector3.up) * (Vector3.up * 40f + Vector3.forward * 5f); + Quaternion quaternion = Quaternion.AngleAxis(angle, Vector3.up); + Vector3 position = base.gameObject.transform.position + rewardOffset; + int num2 = 0; + while (num2 < num) + { + GenericPickupController.CreatePickupInfo pickupInfo = default(GenericPickupController.CreatePickupInfo); + pickupInfo.pickupIndex = PickupCatalog.FindPickupIndex(rewardDisplayTier); + pickupInfo.pickerOptions = PickupPickerController.GenerateOptionsFromDropTable(rewardOptionCount, rewardDropTable, rng); + pickupInfo.rotation = Quaternion.identity; + pickupInfo.prefabOverride = rewardPickupPrefab; + PickupDropletController.CreatePickupDroplet(pickupInfo, position, vector); + num2++; + vector = quaternion * vector; + } + } + if (base.fixedAge >= itemGrantingDuration) + { + if (FalseSonUnlockStateMet()) + { + outer.SetNextState(new AurelioniteHeartFalseSonSurvivorUnlockState()); + } + else + { + outer.SetNextState(new AurelioniteHeartInertState()); + } + } + } + + private bool FalseSonUnlockStateMet() + { + bool result = false; + int num = 0; + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + if (!instance.networkUser.localUser.userProfile.HasAchievement("UnlockFalseSon")) + { + num++; + } + } + if (num > 0) + { + foreach (PlayerCharacterMasterController instance2 in PlayerCharacterMasterController.instances) + { + if (instance2.master.inventory.GetItemCount(RoR2Content.Items.TitanGoldDuringTP) > 0 && num > 0) + { + result = true; + GameObject effectPrefab = LegacyResourcesAPI.Load("Prefabs/Effects/DelusionItemDissolveVFX"); + EffectData effectData = new EffectData + { + origin = instance2.master.GetBody().transform.position, + genericFloat = 1.5f, + genericUInt = (uint)(halcyonSeed.itemIndex + 1) + }; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + instance2.master.inventory.RemoveItem(halcyonSeed); + FalseSonUnlocked(); + } + } + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartEntityState.cs b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartEntityState.cs new file mode 100644 index 0000000..872ea9b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartEntityState.cs @@ -0,0 +1,34 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.AurelioniteHeart; + +public class AurelioniteHeartEntityState : EntityState +{ + protected AurelioniteHeartController heartController; + + protected Animator animator; + + protected Xoroshiro128Plus rng; + + protected Vector3 inertPosition; + + protected float heartMovementTimer; + + public static event Action falseSonUnlockEvent; + + public override void OnEnter() + { + base.OnEnter(); + heartController = base.gameObject.GetComponent(); + animator = heartController.heartAnimator; + rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong); + inertPosition = new Vector3(base.gameObject.transform.position.x, base.gameObject.transform.position.y - 1f, base.gameObject.transform.position.z); + } + + public void FalseSonUnlocked() + { + AurelioniteHeartEntityState.falseSonUnlockEvent?.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartFalseSonSurvivorUnlockState.cs b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartFalseSonSurvivorUnlockState.cs new file mode 100644 index 0000000..6aea8d9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartFalseSonSurvivorUnlockState.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +namespace EntityStates.AurelioniteHeart; + +public class AurelioniteHeartFalseSonSurvivorUnlockState : AurelioniteHeartEntityState +{ + [SerializeField] + public float animationDuration = 4f; + + [SerializeField] + public float initialDelay = 2f; + + [SerializeField] + public string falseSonUnlockAnimationState; + + [SerializeField] + public float upwardMovement = 0.2f; + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!(base.fixedAge >= initialDelay)) + { + return; + } + heartMovementTimer -= GetDeltaTime(); + base.gameObject.transform.position += new Vector3(0f, upwardMovement, 0f); + if (heartMovementTimer <= 0f) + { + heartMovementTimer += 0.02f; + upwardMovement += upwardMovement / 10f; + if (base.fixedAge >= animationDuration) + { + heartController.rebirthShrine.SetActive(value: true); + EntityState.Destroy(base.gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartIdleState.cs b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartIdleState.cs new file mode 100644 index 0000000..7bf4797 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartIdleState.cs @@ -0,0 +1,9 @@ +namespace EntityStates.AurelioniteHeart; + +public class AurelioniteHeartIdleState : AurelioniteHeartEntityState +{ + public override void OnEnter() + { + base.OnEnter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartInertState.cs b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartInertState.cs new file mode 100644 index 0000000..f12d204 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.AurelioniteHeart/AurelioniteHeartInertState.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace EntityStates.AurelioniteHeart; + +public class AurelioniteHeartInertState : AurelioniteHeartEntityState +{ + [SerializeField] + private float animationDuration = 1f; + + [SerializeField] + private string heartInertAnimationState; + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + heartMovementTimer -= GetDeltaTime(); + if (heartMovementTimer <= 0f) + { + heartMovementTimer += 0.02f; + if (base.gameObject.transform.position != inertPosition) + { + base.gameObject.transform.position += new Vector3(0f, -0.25f, 0f); + return; + } + animator.StopPlayback(); + heartController.rebirthShrine.SetActive(value: true); + outer.SetNextState(new AurelioniteHeartIdleState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FirePrimaryBase.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FirePrimaryBase.cs new file mode 100644 index 0000000..5c0702d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FirePrimaryBase.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public abstract class Bandit2FirePrimaryBase : GenericBulletBaseState +{ + [SerializeField] + public float minimumBaseDuration; + + protected float minimumDuration; + + private static int FireMainWeaponStateHash = Animator.StringToHash("FireMainWeapon"); + + private static int FireMainWeaponParamHash = Animator.StringToHash("FireMainWeapon.playbackRate"); + + public override void OnEnter() + { + minimumDuration = minimumBaseDuration / attackSpeedStat; + base.OnEnter(); + PlayAnimation("Gesture, Additive", FireMainWeaponStateHash, FireMainWeaponParamHash, duration); + } + + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.falloffModel = BulletAttack.FalloffModel.DefaultBullet; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge > minimumDuration)) + { + return InterruptPriority.Skill; + } + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FireRifle.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FireRifle.cs new file mode 100644 index 0000000..95a4dab --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FireRifle.cs @@ -0,0 +1,12 @@ +using RoR2; + +namespace EntityStates.Bandit2.Weapon; + +public class Bandit2FireRifle : Bandit2FirePrimaryBase +{ + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FireShiv.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FireShiv.cs new file mode 100644 index 0000000..5a70f7d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Bandit2FireShiv.cs @@ -0,0 +1,109 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public class Bandit2FireShiv : BaseSkillState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public int maxShivCount; + + public static float baseDelayBetweenShivs; + + public static float shortHopVelocity; + + public static GameObject muzzleEffectPrefab; + + public static string muzzleString; + + private float duration; + + private float delayBetweenShivs; + + private float countdownSinceLastShiv; + + private int shivCount; + + private static int SlashBladeStateHash = Animator.StringToHash("SlashBlade"); + + private static int SlashBladeParamHash = Animator.StringToHash("SlashBlade.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + delayBetweenShivs = baseDelayBetweenShivs / attackSpeedStat; + PlayAnimation("Gesture, Additive", SlashBladeStateHash, SlashBladeParamHash, duration); + StartAimMode(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = new Vector3(base.characterMotor.velocity.x, Mathf.Max(base.characterMotor.velocity.y, shortHopVelocity), base.characterMotor.velocity.z); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + countdownSinceLastShiv -= GetDeltaTime(); + if (shivCount < maxShivCount && countdownSinceLastShiv <= 0f) + { + shivCount++; + countdownSinceLastShiv += delayBetweenShivs; + FireShiv(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireShiv() + { + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + Ray ray = GetAimRay(); + if (projectilePrefab != null) + { + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.damageTypeOverride = DamageType.SuperBleedOnCrit; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BaseFireSidearmRevolverState.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BaseFireSidearmRevolverState.cs new file mode 100644 index 0000000..07393de --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BaseFireSidearmRevolverState.cs @@ -0,0 +1,107 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public abstract class BaseFireSidearmRevolverState : BaseSidearmState +{ + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject tracerEffectPrefab; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public float minSpread; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bulletRadius; + + [SerializeField] + public float trajectoryAimAssistMultiplier = 0.75f; + + private static int FireSideWeaponStateHash = Animator.StringToHash("FireSideWeapon"); + + private static int FireSideWeaponParamHash = Animator.StringToHash("FireSideWeapon.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + AddRecoil(-3f * recoilAmplitude, -4f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "MuzzlePistol"; + Util.PlaySound(attackSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", FireSideWeaponStateHash, FireSideWeaponParamHash, duration); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = RollCrit(); + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = bulletRadius; + bulletAttack.damageType |= (DamageTypeCombo)DamageType.BonusToLowHealth; + bulletAttack.smartCollision = true; + bulletAttack.trajectoryAimAssistMultiplier = trajectoryAimAssistMultiplier; + ModifyBullet(bulletAttack); + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new ExitSidearmRevolver()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } + + protected virtual void ModifyBullet(BulletAttack bulletAttack) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BasePrepSidearmRevolverState.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BasePrepSidearmRevolverState.cs new file mode 100644 index 0000000..9864755 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BasePrepSidearmRevolverState.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public abstract class BasePrepSidearmRevolverState : BaseSidearmState +{ + [SerializeField] + public string enterSoundString; + + private Animator animator; + + private static int MainToSideStateHash = Animator.StringToHash("MainToSide"); + + private static int MainToSideParamHash = Animator.StringToHash("MainToSide.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Gesture, Additive", MainToSideStateHash, MainToSideParamHash, duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(GetNextState()); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + protected abstract EntityState GetNextState(); +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BaseSidearmState.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BaseSidearmState.cs new file mode 100644 index 0000000..e2c82ad --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/BaseSidearmState.cs @@ -0,0 +1,70 @@ +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public class BaseSidearmState : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + protected float duration; + + private Animator animator; + + private int bodySideWeaponLayerIndex; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + public virtual string exitAnimationStateName => "BufferEmpty"; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + duration = baseDuration / attackSpeedStat; + if ((bool)animator) + { + bodySideWeaponLayerIndex = animator.GetLayerIndex("Body, SideWeapon"); + animator.SetLayerWeight(bodySideWeaponLayerIndex, 1f); + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + base.characterBody.SetAimTimer(3f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.characterBody.isSprinting) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)animator) + { + animator.SetLayerWeight(bodySideWeaponLayerIndex, 0f); + } + PlayAnimation("Gesture, Additive", exitAnimationStateName); + crosshairOverrideRequest?.Dispose(); + Transform transform = FindModelChild("SpinningPistolFX"); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/EnterReload.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/EnterReload.cs new file mode 100644 index 0000000..6d74e07 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/EnterReload.cs @@ -0,0 +1,33 @@ +using RoR2; + +namespace EntityStates.Bandit2.Weapon; + +public class EnterReload : BaseState +{ + public static string enterSoundString; + + public static float baseDuration; + + private float duration => baseDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Gesture, Additive", "EnterReload", "Reload.playbackRate", duration, 0.1f); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new Reload()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/ExitSidearmRevolver.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/ExitSidearmRevolver.cs new file mode 100644 index 0000000..05efece --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/ExitSidearmRevolver.cs @@ -0,0 +1,20 @@ +namespace EntityStates.Bandit2.Weapon; + +public class ExitSidearmRevolver : BaseSidearmState +{ + public override string exitAnimationStateName => "SideToMain"; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireShotgun2.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireShotgun2.cs new file mode 100644 index 0000000..6028a32 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireShotgun2.cs @@ -0,0 +1,56 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public class FireShotgun2 : Bandit2FirePrimaryBase +{ + [SerializeField] + public float minFixedSpreadYaw; + + [SerializeField] + public float maxFixedSpreadYaw; + + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.bulletCount = 1u; + bulletAttack.allowTrajectoryAimAssist = false; + } + + protected override void FireBullet(Ray aimRay) + { + StartAimMode(aimRay, 3f); + DoFireEffects(); + PlayFireAnimation(); + AddRecoil(-1f * recoilAmplitudeY, -1.5f * recoilAmplitudeY, -1f * recoilAmplitudeX, 1f * recoilAmplitudeX); + if (base.isAuthority) + { + Vector3 rhs = Vector3.Cross(Vector3.up, aimRay.direction); + Vector3 axis = Vector3.Cross(aimRay.direction, rhs); + float num = 0f; + if ((bool)base.characterBody) + { + num = base.characterBody.spreadBloomAngle; + } + float angle = 0f; + float num2 = 0f; + if (bulletCount > 1) + { + num2 = Random.Range(minFixedSpreadYaw + num, maxFixedSpreadYaw + num) * 2f; + angle = num2 / (float)(bulletCount - 1); + } + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref aimRay, maxDistance, base.gameObject); + Vector3 direction = Quaternion.AngleAxis((0f - num2) * 0.5f, axis) * aimRay.direction; + Quaternion quaternion = Quaternion.AngleAxis(angle, axis); + Ray aimRay2 = new Ray(aimRay.origin, direction); + for (int i = 0; i < bulletCount; i++) + { + BulletAttack bulletAttack = GenerateBulletAttack(aimRay2); + ModifyBullet(bulletAttack); + bulletAttack.Fire(); + aimRay2.direction = quaternion * aimRay2.direction; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireSidearmResetRevolver.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireSidearmResetRevolver.cs new file mode 100644 index 0000000..2f6e6e0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireSidearmResetRevolver.cs @@ -0,0 +1,12 @@ +using RoR2; + +namespace EntityStates.Bandit2.Weapon; + +public class FireSidearmResetRevolver : BaseFireSidearmRevolverState +{ + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.damageType |= (DamageTypeCombo)DamageType.ResetCooldownsOnKill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireSidearmSkullRevolver.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireSidearmSkullRevolver.cs new file mode 100644 index 0000000..7038b7b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/FireSidearmSkullRevolver.cs @@ -0,0 +1,18 @@ +using RoR2; + +namespace EntityStates.Bandit2.Weapon; + +public class FireSidearmSkullRevolver : BaseFireSidearmRevolverState +{ + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + int num = 0; + if ((bool)base.characterBody) + { + num = base.characterBody.GetBuffCount(RoR2Content.Buffs.BanditSkull); + } + bulletAttack.damage *= 1f + 0.1f * (float)num; + bulletAttack.damageType |= (DamageTypeCombo)DamageType.GiveSkullOnKill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/PrepSidearmResetRevolver.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/PrepSidearmResetRevolver.cs new file mode 100644 index 0000000..b442508 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/PrepSidearmResetRevolver.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Bandit2.Weapon; + +public class PrepSidearmResetRevolver : BasePrepSidearmRevolverState +{ + protected override EntityState GetNextState() + { + return new FireSidearmResetRevolver(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/PrepSidearmSkullRevolver.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/PrepSidearmSkullRevolver.cs new file mode 100644 index 0000000..cf645fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/PrepSidearmSkullRevolver.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Bandit2.Weapon; + +public class PrepSidearmSkullRevolver : BasePrepSidearmRevolverState +{ + protected override EntityState GetNextState() + { + return new FireSidearmSkullRevolver(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Reload.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Reload.cs new file mode 100644 index 0000000..807563d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/Reload.cs @@ -0,0 +1,77 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public class Reload : BaseState +{ + public static float enterSoundPitch; + + public static float exitSoundPitch; + + public static string enterSoundString; + + public static string exitSoundString; + + public static GameObject reloadEffectPrefab; + + public static string reloadEffectMuzzleString; + + public static float baseDuration; + + private bool hasGivenStock; + + private static int ReloadSimpleStateHash = Animator.StringToHash("ReloadSimple"); + + private static int ReloadStateHash = Animator.StringToHash("Reload"); + + private static int ReloadParamHash = Animator.StringToHash("Reload.playbackRate"); + + private float duration => baseDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Gesture, Additive", (base.characterBody.isSprinting && (bool)base.characterMotor && base.characterMotor.isGrounded) ? ReloadSimpleStateHash : ReloadStateHash, ReloadParamHash, duration); + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, enterSoundPitch); + EffectManager.SimpleMuzzleFlash(reloadEffectPrefab, base.gameObject, reloadEffectMuzzleString, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration / 2f) + { + GiveStock(); + } + if (base.isAuthority && base.fixedAge >= duration) + { + if (base.skillLocator.primary.stock < base.skillLocator.primary.maxStock) + { + outer.SetNextState(new Reload()); + return; + } + Util.PlayAttackSpeedSound(exitSoundString, base.gameObject, exitSoundPitch); + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void GiveStock() + { + if (!hasGivenStock) + { + base.skillLocator.primary.AddOneStock(); + hasGivenStock = true; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/SlashBlade.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/SlashBlade.cs new file mode 100644 index 0000000..2bf8863 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2.Weapon/SlashBlade.cs @@ -0,0 +1,73 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bandit2.Weapon; + +public class SlashBlade : BasicMeleeAttack +{ + public static float shortHopVelocity; + + public static float selfForceStrength; + + public static float minimumBaseDuration; + + public static AnimationCurve bloomCurve; + + private GameObject bladeMeshObject; + + private static int SlashBladeStateHash = Animator.StringToHash("SlashBlade"); + + private static int SlashBladeParamHash = Animator.StringToHash("SlashBlade.playbackRate"); + + private float minimumDuration => minimumBaseDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Gesture, Additive", SlashBladeStateHash, SlashBladeParamHash, duration); + bladeMeshObject = FindModelChild("BladeMesh").gameObject; + if ((bool)bladeMeshObject) + { + bladeMeshObject.SetActive(value: true); + } + base.characterMotor.ApplyForce(base.inputBank.moveVector * selfForceStrength, alwaysApply: true); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = new Vector3(base.characterMotor.velocity.x, Mathf.Max(base.characterMotor.velocity.y, shortHopVelocity), base.characterMotor.velocity.z); + } + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + overlapAttack.damageType = DamageType.SuperBleedOnCrit; + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(bloomCurve.Evaluate(base.age / duration), canOnlyIncreaseBloom: false); + } + + public override void OnExit() + { + if ((bool)bladeMeshObject) + { + bladeMeshObject.SetActive(value: false); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if ((bool)base.inputBank) + { + if (!(base.fixedAge > minimumDuration)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Skill; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2/StealthMode.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2/StealthMode.cs new file mode 100644 index 0000000..fad6623 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2/StealthMode.cs @@ -0,0 +1,123 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Bandit2; + +public class StealthMode : BaseState +{ + public static float duration; + + public static string enterStealthSound; + + public static string exitStealthSound; + + public static float blastAttackRadius; + + public static float blastAttackDamageCoefficient; + + public static float blastAttackProcCoefficient; + + public static float blastAttackForce; + + public static GameObject smokeBombEffectPrefab; + + public static string smokeBombMuzzleString; + + public static float shortHopVelocity; + + private Animator animator; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + _ = (bool)animator; + if ((bool)base.characterBody) + { + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Cloak); + base.characterBody.AddBuff(RoR2Content.Buffs.CloakSpeed); + } + base.characterBody.onSkillActivatedAuthority += OnSkillActivatedAuthority; + } + FireSmokebomb(); + Util.PlaySound(enterStealthSound, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + FireSmokebomb(); + } + Util.PlaySound(exitStealthSound, base.gameObject); + if ((bool)base.characterBody) + { + base.characterBody.onSkillActivatedAuthority -= OnSkillActivatedAuthority; + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.CloakSpeed); + base.characterBody.RemoveBuff(RoR2Content.Buffs.Cloak); + } + } + if ((bool)animator) + { + animator.SetLayerWeight(animator.GetLayerIndex("Body, StealthWeapon"), 0f); + } + base.OnExit(); + } + + private void OnSkillActivatedAuthority(GenericSkill skill) + { + if (skill.skillDef.isCombatSkill) + { + outer.SetNextStateToMain(); + } + } + + private void FireSmokebomb() + { + if (base.isAuthority) + { + BlastAttack obj = new BlastAttack + { + radius = blastAttackRadius, + procCoefficient = blastAttackProcCoefficient, + position = base.transform.position, + attacker = base.gameObject, + crit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master), + baseDamage = base.characterBody.damage * blastAttackDamageCoefficient, + falloffModel = BlastAttack.FalloffModel.None, + damageType = DamageType.Stun1s, + baseForce = blastAttackForce + }; + obj.teamIndex = TeamComponent.GetObjectTeam(obj.attacker); + obj.attackerFiltering = AttackerFiltering.NeverHitSelf; + obj.Fire(); + } + if ((bool)smokeBombEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(smokeBombEffectPrefab, base.gameObject, smokeBombMuzzleString, transmit: false); + } + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = new Vector3(base.characterMotor.velocity.x, shortHopVelocity, base.characterMotor.velocity.z); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bandit2/ThrowSmokebomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Bandit2/ThrowSmokebomb.cs new file mode 100644 index 0000000..3299657 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bandit2/ThrowSmokebomb.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +namespace EntityStates.Bandit2; + +public class ThrowSmokebomb : BaseState +{ + public static float duration; + + private static int throwSmokeBombStateHash = Animator.StringToHash("ThrowSmokebomb"); + + private static int throwSmokeBombParamHash = Animator.StringToHash("ThrowSmokebomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Gesture, Additive", throwSmokeBombStateHash, throwSmokeBombParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new StealthMode()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Barrel/ActivateFan.cs b/ilspy_dump/ror2_csproj/EntityStates.Barrel/ActivateFan.cs new file mode 100644 index 0000000..d724af6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Barrel/ActivateFan.cs @@ -0,0 +1,30 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Barrel; + +public class ActivateFan : EntityState +{ + private static int IdleToActiveStateHash = Animator.StringToHash("IdleToActive"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", IdleToActiveStateHash); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.FindChild("JumpVolume").gameObject.SetActive(value: true); + component.FindChild("LightBack").gameObject.SetActive(value: true); + component.FindChild("LightFront").gameObject.SetActive(value: true); + } + } + if ((bool)base.sfxLocator) + { + Util.PlaySound(base.sfxLocator.openSound, base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Barrel/Closed.cs b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Closed.cs new file mode 100644 index 0000000..9e87d1b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Closed.cs @@ -0,0 +1,10 @@ +namespace EntityStates.Barrel; + +public class Closed : EntityState +{ + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", "Closed"); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Barrel/Closing.cs b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Closing.cs new file mode 100644 index 0000000..4c3d0b8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Closing.cs @@ -0,0 +1,21 @@ +namespace EntityStates.Barrel; + +public class Closing : EntityState +{ + public static float duration = 1f; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", "Closing", "Closing.playbackRate", duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new Closed()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Barrel/Opened.cs b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Opened.cs new file mode 100644 index 0000000..a5dc9e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Opened.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +namespace EntityStates.Barrel; + +public class Opened : EntityState +{ + private static int OpenedStateHash = Animator.StringToHash("Opened"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", OpenedStateHash); + SetPingable(value: false); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Barrel/Opening.cs b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Opening.cs new file mode 100644 index 0000000..74c3b71 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Barrel/Opening.cs @@ -0,0 +1,32 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Barrel; + +public class Opening : EntityState +{ + public static float duration = 1f; + + private static int OpeningStateHash = Animator.StringToHash("Opening"); + + private static int OpeningParamHash = Animator.StringToHash("Opening.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", OpeningStateHash, OpeningParamHash, duration); + if ((bool)base.sfxLocator) + { + Util.PlaySound(base.sfxLocator.openSound, base.gameObject); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new Opened()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Barrel/OpeningLunar.cs b/ilspy_dump/ror2_csproj/EntityStates.Barrel/OpeningLunar.cs new file mode 100644 index 0000000..083587f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Barrel/OpeningLunar.cs @@ -0,0 +1,57 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Barrel; + +public class OpeningLunar : BaseState +{ + public static float duration = 1f; + + private static int OpeningStateHash = Animator.StringToHash("Opening"); + + private static int OpeningParamHash = Animator.StringToHash("Opening.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", OpeningStateHash, OpeningParamHash, duration); + if ((bool)base.sfxLocator) + { + Util.PlaySound(base.sfxLocator.openSound, base.gameObject); + } + StopSteamEffect(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new Opened()); + } + } + + private void StopSteamEffect() + { + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("SteamEffect"); + if ((bool)transform) + { + ParticleSystem component2 = transform.GetComponent(); + if ((bool)component2) + { + ParticleSystem.MainModule main = component2.main; + main.loop = false; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/DefenseUp.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/DefenseUp.cs new file mode 100644 index 0000000..54fa7f1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/DefenseUp.cs @@ -0,0 +1,89 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BeetleGuardMonster; + +public class DefenseUp : BaseState +{ + public static float baseDuration = 3.5f; + + public static float buffDuration = 8f; + + public static GameObject defenseUpPrefab; + + private Animator modelAnimator; + + private float duration; + + private bool hasCastBuff; + + private EffectManagerHelper _emh_defenseUp; + + public override void Reset() + { + base.Reset(); + modelAnimator = null; + duration = 0f; + hasCastBuff = false; + _emh_defenseUp = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayCrossfade("Body", "DefenseUp", "DefenseUp.playbackRate", duration, 0.2f); + } + } + + public override void OnExit() + { + if (_emh_defenseUp != null && _emh_defenseUp.OwningPool != null) + { + _emh_defenseUp.OwningPool.ReturnObject(_emh_defenseUp); + _emh_defenseUp = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("DefenseUp.activate") > 0.5f && !hasCastBuff) + { + GameObject gameObject = null; + if (!EffectManager.ShouldUsePooledEffect(defenseUpPrefab)) + { + gameObject = Object.Instantiate(defenseUpPrefab, base.transform.position, Quaternion.identity, base.transform); + } + else + { + _emh_defenseUp = EffectManager.GetAndActivatePooledEffect(defenseUpPrefab, base.transform.position, Quaternion.identity, base.transform); + gameObject = _emh_defenseUp.gameObject; + } + ScaleParticleSystemDuration component = gameObject.GetComponent(); + if ((bool)component) + { + component.newDuration = buffDuration; + } + hasCastBuff = true; + if (NetworkServer.active) + { + base.characterBody.AddTimedBuff(JunkContent.Buffs.EnrageAncientWisp, buffDuration); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/FireSunder.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/FireSunder.cs new file mode 100644 index 0000000..98c1395 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/FireSunder.cs @@ -0,0 +1,144 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.BeetleGuardMonster; + +public class FireSunder : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static string initialAttackSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject projectilePrefab; + + public static GameObject hitEffectPrefab; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + private float duration; + + private GameObject rightHandChargeEffect; + + private ChildLocator modelChildLocator; + + private Transform handRTransform; + + private EffectManagerHelper _emh_rightHandChargeEffect; + + public override void Reset() + { + base.Reset(); + modelAnimator = null; + modelTransform = null; + hasAttacked = false; + duration = 0f; + rightHandChargeEffect = null; + modelChildLocator = null; + handRTransform = null; + _emh_rightHandChargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + Util.PlaySound(initialAttackSoundString, base.gameObject); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "FireSunder", "FireSunder.playbackRate", duration, 0.2f); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration + 2f); + } + if (!modelTransform) + { + return; + } + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + modelChildLocator = modelTransform.GetComponent(); + if (!modelChildLocator) + { + return; + } + GameObject gameObject = chargeEffectPrefab; + handRTransform = modelChildLocator.FindChild("HandR"); + if ((bool)handRTransform) + { + if (!EffectManager.ShouldUsePooledEffect(gameObject)) + { + rightHandChargeEffect = Object.Instantiate(gameObject, handRTransform); + return; + } + _emh_rightHandChargeEffect = EffectManager.GetAndActivatePooledEffect(gameObject, handRTransform, inResetLocal: true); + rightHandChargeEffect = _emh_rightHandChargeEffect.gameObject; + } + } + + public override void OnExit() + { + DestroyRightHandCharge(); + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + } + base.OnExit(); + } + + public void DestroyRightHandCharge() + { + if (_emh_rightHandChargeEffect != null && _emh_rightHandChargeEffect.OwningPool != null) + { + _emh_rightHandChargeEffect.OwningPool.ReturnObject(_emh_rightHandChargeEffect); + } + else + { + EntityState.Destroy(rightHandChargeEffect); + } + rightHandChargeEffect = null; + _emh_rightHandChargeEffect = null; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("FireSunder.activate") > 0.5f && !hasAttacked) + { + if (base.isAuthority && (bool)modelTransform) + { + Ray aimRay = GetAimRay(); + aimRay.origin = handRTransform.position; + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, forceMagnitude, Util.CheckRoll(critStat, base.characterBody.master)); + } + hasAttacked = true; + DestroyRightHandCharge(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/GroundSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/GroundSlam.cs new file mode 100644 index 0000000..629a875 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/GroundSlam.cs @@ -0,0 +1,205 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BeetleGuardMonster; + +public class GroundSlam : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + private OverlapAttack attack; + + public static string initialAttackSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject slamEffectPrefab; + + public static GameObject hitEffectPrefab; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + private float duration; + + private GameObject leftHandChargeEffect; + + private GameObject rightHandChargeEffect; + + private ChildLocator modelChildLocator; + + private EffectManagerHelper _emh_leftHandChargeEffect; + + private EffectManagerHelper _emh_rightHandChargeEffect; + + private Transform groundSlamIndicatorInstance; + + public override void Reset() + { + base.Reset(); + if (attack != null) + { + attack.Reset(); + } + modelAnimator = null; + modelTransform = null; + hasAttacked = false; + duration = 0f; + leftHandChargeEffect = null; + rightHandChargeEffect = null; + modelChildLocator = null; + _emh_leftHandChargeEffect = null; + _emh_rightHandChargeEffect = null; + groundSlamIndicatorInstance = null; + } + + private void EnableIndicator(Transform indicator) + { + if ((bool)indicator) + { + indicator.gameObject.SetActive(value: true); + ObjectScaleCurve component = indicator.gameObject.GetComponent(); + if ((bool)component) + { + component.time = 0f; + } + } + } + + private void DisableIndicator(Transform indicator) + { + if ((bool)indicator) + { + indicator.gameObject.SetActive(value: false); + } + } + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + Util.PlaySound(initialAttackSoundString, base.gameObject); + _ = (bool)base.characterDirection; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.forceVector = Vector3.up * forceMagnitude; + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "GroundSlam"); + } + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "GroundSlam", "GroundSlam.playbackRate", duration, 0.2f); + if (!modelTransform) + { + return; + } + modelChildLocator = modelTransform.GetComponent(); + if (!modelChildLocator) + { + return; + } + GameObject gameObject = chargeEffectPrefab; + Transform transform = modelChildLocator.FindChild("HandL"); + Transform transform2 = modelChildLocator.FindChild("HandR"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(gameObject)) + { + leftHandChargeEffect = UnityEngine.Object.Instantiate(gameObject, transform); + } + else + { + _emh_leftHandChargeEffect = EffectManager.GetAndActivatePooledEffect(gameObject, transform, inResetLocal: true); + leftHandChargeEffect = _emh_leftHandChargeEffect.gameObject; + } + } + if ((bool)transform2) + { + if (!EffectManager.ShouldUsePooledEffect(gameObject)) + { + rightHandChargeEffect = UnityEngine.Object.Instantiate(gameObject, transform2); + } + else + { + _emh_rightHandChargeEffect = EffectManager.GetAndActivatePooledEffect(gameObject, transform2, inResetLocal: true); + rightHandChargeEffect = _emh_rightHandChargeEffect.gameObject; + } + } + groundSlamIndicatorInstance = modelChildLocator.FindChild("GroundSlamIndicator"); + EnableIndicator(groundSlamIndicatorInstance); + } + + protected void DestroyChargeEffects() + { + if (_emh_leftHandChargeEffect != null && _emh_leftHandChargeEffect.OwningPool != null) + { + _emh_leftHandChargeEffect.OwningPool.ReturnObject(_emh_leftHandChargeEffect); + } + else + { + EntityState.Destroy(leftHandChargeEffect); + } + leftHandChargeEffect = null; + _emh_leftHandChargeEffect = null; + if (_emh_rightHandChargeEffect != null && _emh_rightHandChargeEffect.OwningPool != null) + { + _emh_rightHandChargeEffect.OwningPool.ReturnObject(_emh_rightHandChargeEffect); + } + else + { + EntityState.Destroy(rightHandChargeEffect); + } + rightHandChargeEffect = null; + _emh_rightHandChargeEffect = null; + } + + public override void OnExit() + { + DestroyChargeEffects(); + DisableIndicator(groundSlamIndicatorInstance); + _ = (bool)base.characterDirection; + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("GroundSlam.hitBoxActive") > 0.5f && !hasAttacked) + { + if (NetworkServer.active) + { + attack.Fire(); + } + if (base.isAuthority && (bool)modelTransform) + { + DisableIndicator(groundSlamIndicatorInstance); + EffectManager.SimpleMuzzleFlash(slamEffectPrefab, base.gameObject, "SlamZone", transmit: true); + } + hasAttacked = true; + DestroyChargeEffects(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/SpawnState.cs new file mode 100644 index 0000000..a541ce6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleGuardMonster/SpawnState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BeetleGuardMonster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + private static int Spawn1StateHash = Animator.StringToHash("Spawn1"); + + private static int Spawn1ParamHash = Animator.StringToHash("Spawn1.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", Spawn1StateHash, Spawn1ParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/HeadbuttState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/HeadbuttState.cs new file mode 100644 index 0000000..9ffc2e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/HeadbuttState.cs @@ -0,0 +1,81 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.BeetleMonster; + +public class HeadbuttState : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient; + + public static float forceMagnitude = 16f; + + public static GameObject hitEffectPrefab; + + public static string attackSoundString; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private RootMotionAccumulator rootMotionAccumulator; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + rootMotionAccumulator = GetModelRootMotionAccumulator(); + modelAnimator = GetModelAnimator(); + duration = baseDuration / attackSpeedStat; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Headbutt"); + } + Util.PlaySound(attackSoundString, base.gameObject); + PlayCrossfade("Body", "Headbutt", "Headbutt.playbackRate", duration, 0.1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)rootMotionAccumulator) + { + Vector3 vector = rootMotionAccumulator.ExtractRootMotion(); + if (vector != Vector3.zero && base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.rootMotion += vector; + } + } + if (base.isAuthority) + { + attack.forceVector = (base.characterDirection ? (base.characterDirection.forward * forceMagnitude) : Vector3.zero); + if ((bool)base.characterDirection && (bool)base.inputBank) + { + base.characterDirection.moveVector = base.inputBank.aimDirection; + } + if ((bool)modelAnimator && modelAnimator.GetFloat("Headbutt.hitBoxActive") > 0.5f) + { + attack.Fire(); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/MainState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/MainState.cs new file mode 100644 index 0000000..429d825 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/MainState.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +namespace EntityStates.BeetleMonster; + +public class MainState : EntityState +{ + private Animator modelAnimator; + + private static int walkToRunBlendParamHash = Animator.StringToHash("walkToRunBlend"); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.CrossFadeInFixedTime("Walk", 0.1f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(walkToRunBlendParamHash, 1f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/MeleeState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/MeleeState.cs new file mode 100644 index 0000000..13a0db9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/MeleeState.cs @@ -0,0 +1,57 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.BeetleMonster; + +public class MeleeState : EntityState +{ + public static float duration = 3.5f; + + public static float damage = 10f; + + public static float forceMagnitude = 10f; + + private OverlapAttack attack; + + private Animator modelAnimator; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = 10f; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Melee1"); + } + PlayCrossfade("Body", "Melee1", "Melee1.playbackRate", duration, 0.1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + attack.forceVector = (base.characterDirection ? (base.characterDirection.forward * forceMagnitude) : Vector3.zero); + if ((bool)modelAnimator && modelAnimator.GetFloat("Melee1.hitBoxActive") > 0.5f) + { + attack.Fire(); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/SpawnState.cs new file mode 100644 index 0000000..c0181f9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleMonster/SpawnState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.BeetleMonster; + +public class SpawnState : GenericCharacterSpawnState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/BeetleWardDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/BeetleWardDeath.cs new file mode 100644 index 0000000..003d50a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/BeetleWardDeath.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BeetleQueenMonster; + +public class BeetleWardDeath : BaseState +{ + public static GameObject initialExplosion; + + public static string deathString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(deathString, base.gameObject); + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)initialExplosion && NetworkServer.active) + { + EffectManager.SimpleImpactEffect(initialExplosion, base.transform.position, Vector3.up, transmit: true); + } + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/BeginBurrow.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/BeginBurrow.cs new file mode 100644 index 0000000..ece1646 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/BeginBurrow.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +namespace EntityStates.BeetleQueenMonster; + +public class BeginBurrow : BaseState +{ + public static GameObject burrowPrefab; + + public static float duration; + + private bool isBurrowing; + + private Animator animator; + + private Transform modelTransform; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + PlayCrossfade("Body", "BeginBurrow", "BeginBurrow.playbackRate", duration, 0.5f); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + bool flag = animator.GetFloat("BeginBurrow.active") > 0.9f; + if (flag && !isBurrowing) + { + string childName = "BurrowCenter"; + Transform transform = childLocator.FindChild(childName); + if ((bool)transform) + { + Object.Instantiate(burrowPrefab, transform.position, Quaternion.identity); + } + } + isBurrowing = flag; + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/ChargeSpit.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/ChargeSpit.cs new file mode 100644 index 0000000..b08275d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/ChargeSpit.cs @@ -0,0 +1,106 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BeetleQueenMonster; + +public class ChargeSpit : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject effectPrefab; + + public static string attackSoundString; + + private float duration; + + private GameObject chargeEffect; + + private EffectManagerHelper _emh_chargeEffect; + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffect = null; + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayCrossfade("Gesture", "ChargeSpit", "ChargeSpit.playbackRate", duration, 0.2f); + Util.PlaySound(attackSoundString, base.gameObject); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component || !effectPrefab) + { + return; + } + Transform transform = component.FindChild("Mouth"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + + public override void OnExit() + { + base.OnExit(); + if (chargeEffect != null) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + chargeEffect = null; + _emh_chargeEffect = null; + } + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if (base.fixedAge >= duration && base.isAuthority) + { + FireSpit nextState = new FireSpit(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/FireSpit.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/FireSpit.cs new file mode 100644 index 0000000..1b013da --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/FireSpit.cs @@ -0,0 +1,94 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.BeetleQueenMonster; + +public class FireSpit : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static int projectileCount = 3; + + public static float yawSpread = 5f; + + public static float minSpread = 0f; + + public static float maxSpread = 5f; + + public static float arcAngle = 5f; + + public static float projectileHSpeed = 50f; + + private Ray aimRay; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + string muzzleName = "Mouth"; + duration = baseDuration / attackSpeedStat; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + PlayCrossfade("Gesture", "FireSpit", "FireSpit.playbackRate", duration, 0.1f); + aimRay = GetAimRay(); + float magnitude = projectileHSpeed; + Ray ray = aimRay; + ray.origin = aimRay.GetPoint(6f); + if (Util.CharacterRaycast(base.gameObject, ray, out var hitInfo, float.PositiveInfinity, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + float num = magnitude; + Vector3 vector = hitInfo.point - aimRay.origin; + Vector2 vector2 = new Vector2(vector.x, vector.z); + float magnitude2 = vector2.magnitude; + float y = Trajectory.CalculateInitialYSpeed(magnitude2 / num, vector.y); + Vector3 vector3 = new Vector3(vector2.x / magnitude2 * num, y, vector2.y / magnitude2 * num); + magnitude = vector3.magnitude; + aimRay.direction = vector3 / magnitude; + } + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + if (base.isAuthority) + { + for (int i = 0; i < projectileCount; i++) + { + FireBlob(aimRay, 0f, ((float)projectileCount / 2f - (float)i) * yawSpread, magnitude); + } + } + } + + private void FireBlob(Ray aimRay, float bonusPitch, float bonusYaw, float speed) + { + Vector3 forward = Util.ApplySpread(aimRay.direction, minSpread, maxSpread, 1f, 1f, bonusYaw, bonusPitch); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, speed); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SpawnState.cs new file mode 100644 index 0000000..c66dbed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SpawnState.cs @@ -0,0 +1,41 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BeetleQueenMonster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static GameObject burrowPrefab; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + GetModelTransform().GetComponent(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + string muzzleName = "BurrowCenter"; + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, muzzleName, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SpawnWards.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SpawnWards.cs new file mode 100644 index 0000000..255d7b6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SpawnWards.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BeetleQueenMonster; + +public class SpawnWards : BaseState +{ + public static string muzzleString; + + public static string attackSoundString; + + public static GameObject muzzleflashEffectPrefab; + + public static float baseDuration = 0.9f; + + public static float orbRange; + + public static float orbTravelSpeed; + + public static int orbCountMax; + + private float stopwatch; + + private int orbCount; + + private float duration; + + private bool hasFiredOrbs; + + private Animator animator; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + childLocator = animator.GetComponent(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("Gesture", "SpawnWards", "SpawnWards.playbackRate", duration, 0.5f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (!hasFiredOrbs && animator.GetFloat("SpawnWards.active") > 0.5f) + { + hasFiredOrbs = true; + FireOrbs(); + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireOrbs() + { + if (NetworkServer.active) + { + Transform transform = childLocator.FindChild(muzzleString).transform; + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = transform.position; + bullseyeSearch.searchDirection = transform.forward; + bullseyeSearch.maxDistanceFilter = orbRange; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(TeamComponent.GetObjectTeam(base.gameObject)); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.RefreshCandidates(); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + List list = bullseyeSearch.GetResults().ToList(); + for (int i = 0; i < list.Count; i++) + { + HurtBox target = list[i]; + BeetleWardOrb beetleWardOrb = new BeetleWardOrb(); + beetleWardOrb.origin = transform.position; + beetleWardOrb.target = target; + beetleWardOrb.speed = orbTravelSpeed; + OrbManager.instance.AddOrb(beetleWardOrb); + } + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)base.cameraTargetParams) + { + base.cameraTargetParams.fovOverride = -1f; + } + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 1.5f); + animator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SummonEggs.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SummonEggs.cs new file mode 100644 index 0000000..a5db336 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/SummonEggs.cs @@ -0,0 +1,168 @@ +using System; +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BeetleQueenMonster; + +public class SummonEggs : BaseState +{ + public static float baseDuration = 3.5f; + + public static string attackSoundString; + + public static float randomRadius = 8f; + + public static GameObject spitPrefab; + + public static int maxSummonCount = 5; + + public static float summonInterval = 1f; + + private static float summonDuration = 3.26f; + + public static SpawnCard spawnCard; + + private Animator animator; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private float duration; + + private float summonTimer; + + private int summonCount; + + private bool isSummoning; + + private BullseyeSearch enemySearch; + + public override void Reset() + { + base.Reset(); + animator = null; + modelTransform = null; + childLocator = null; + duration = 0f; + summonInterval = 0f; + summonTimer = 0f; + summonCount = 0; + isSummoning = false; + } + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + duration = baseDuration; + PlayCrossfade("Gesture", "SummonEggs", 0.5f); + Util.PlaySound(attackSoundString, base.gameObject); + if (NetworkServer.active) + { + enemySearch = new BullseyeSearch(); + enemySearch.filterByDistinctEntity = false; + enemySearch.filterByLoS = false; + enemySearch.maxDistanceFilter = float.PositiveInfinity; + enemySearch.minDistanceFilter = 0f; + enemySearch.minAngleFilter = 0f; + enemySearch.maxAngleFilter = 180f; + enemySearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); + enemySearch.sortMode = BullseyeSearch.SortMode.Distance; + enemySearch.viewer = base.characterBody; + } + } + + private void SummonEgg() + { + Vector3 searchOrigin = GetAimRay().origin; + if ((bool)base.inputBank && base.inputBank.GetAimRaycast(float.PositiveInfinity, out var hitInfo)) + { + searchOrigin = hitInfo.point; + } + if (enemySearch == null) + { + return; + } + enemySearch.searchOrigin = searchOrigin; + enemySearch.RefreshCandidates(); + HurtBox hurtBox = enemySearch.GetResults().FirstOrDefault(); + Transform transform = (((bool)hurtBox && (bool)hurtBox.healthComponent) ? hurtBox.healthComponent.body.coreTransform : base.characterBody.coreTransform); + if (!transform) + { + return; + } + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(spawnCard, new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Approximate, + minDistance = 3f, + maxDistance = 20f, + spawnOnTarget = transform + }, RoR2Application.rng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult spawnResult) + { + if (spawnResult.success && (bool)spawnResult.spawnedInstance && (bool)base.characterBody) + { + Inventory component = spawnResult.spawnedInstance.GetComponent(); + if ((bool)component) + { + component.CopyEquipmentFrom(base.characterBody.inventory); + if (base.characterBody.inventory.GetItemCount(RoR2Content.Items.Ghost) > 0) + { + component.GiveItem(RoR2Content.Items.Ghost); + component.GiveItem(RoR2Content.Items.HealthDecay, 30); + component.GiveItem(RoR2Content.Items.BoostDamage, 150); + } + } + } + }); + DirectorCore.instance?.TrySpawnObject(directorSpawnRequest); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + bool flag = animator.GetFloat("SummonEggs.active") > 0.9f; + if (flag && !isSummoning) + { + string childName = "Mouth"; + Transform transform = childLocator.FindChild(childName); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(spitPrefab)) + { + UnityEngine.Object.Instantiate(spitPrefab, transform); + } + else + { + EffectManager.GetAndActivatePooledEffect(spitPrefab, transform, inResetLocal: true); + } + } + } + if (isSummoning) + { + summonTimer += GetDeltaTime(); + if (NetworkServer.active && summonTimer > 0f && summonCount < maxSummonCount) + { + summonCount++; + summonTimer -= summonInterval; + SummonEgg(); + } + } + isSummoning = flag; + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/WeakState.cs b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/WeakState.cs new file mode 100644 index 0000000..6eed5c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BeetleQueenMonster/WeakState.cs @@ -0,0 +1,93 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BeetleQueenMonster; + +public class WeakState : BaseState +{ + private float stopwatch; + + private float grubStopwatch; + + public static float weakDuration; + + public static float weakToIdleTransitionDuration; + + public static string weakPointChildString; + + public static int maxGrubCount; + + public static float grubSpawnFrequency; + + public static float grubSpawnDelay; + + private int grubCount; + + private bool beginExitTransition; + + private ChildLocator childLocator; + + private static int WeakEnterStateHash = Animator.StringToHash("WeakEnter"); + + public override void OnEnter() + { + base.OnEnter(); + grubStopwatch -= grubSpawnDelay; + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + PlayAnimation("Body", WeakEnterStateHash); + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + childLocator = modelTransform.GetComponent(); + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild(weakPointChildString); + if ((bool)transform) + { + Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/Effects/WeakPointProcEffect"), transform.position, transform.rotation); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + grubStopwatch += deltaTime; + if (grubStopwatch >= 1f / grubSpawnFrequency && grubCount < maxGrubCount) + { + grubCount++; + grubStopwatch -= 1f / grubSpawnFrequency; + if (NetworkServer.active) + { + Transform transform = childLocator.FindChild("GrubSpawnPoint" + Random.Range(1, 10)); + if ((bool)transform) + { + NetworkServer.Spawn(Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/GrubPack"), transform.transform.position, Random.rotation)); + transform.gameObject.SetActive(value: false); + } + } + } + if (stopwatch >= weakDuration - weakToIdleTransitionDuration && !beginExitTransition) + { + beginExitTransition = true; + PlayCrossfade("Body", "WeakExit", "WeakExit.playbackRate", weakToIdleTransitionDuration, 0.5f); + } + if (stopwatch >= weakDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bell.BellWeapon/BuffBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.Bell.BellWeapon/BuffBeam.cs new file mode 100644 index 0000000..511797a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bell.BellWeapon/BuffBeam.cs @@ -0,0 +1,140 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Bell.BellWeapon; + +public class BuffBeam : BaseState +{ + public static float duration; + + public static GameObject buffBeamPrefab; + + public static AnimationCurve beamWidthCurve; + + public static string playBeamSoundString; + + public static string stopBeamSoundString; + + public HurtBox target; + + private float healTimer; + + private float healInterval; + + private float healChunk; + + private CharacterBody targetBody; + + private GameObject buffBeamInstance; + + private BezierCurveLine healBeamCurve; + + private Transform muzzleTransform; + + private Transform beamTipTransform; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(playBeamSoundString, base.gameObject); + Ray aimRay = GetAimRay(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.none; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.AddTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.filterByLoS = false; + bullseyeSearch.maxDistanceFilter = 50f; + bullseyeSearch.maxAngleFilter = 180f; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + target = bullseyeSearch.GetResults().FirstOrDefault(); + Debug.LogFormat("Buffing target {0}", target); + if ((bool)target) + { + targetBody = target.healthComponent.body; + targetBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + string childName = "Muzzle"; + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild(childName); + buffBeamInstance = Object.Instantiate(buffBeamPrefab); + ChildLocator component2 = buffBeamInstance.GetComponent(); + if ((bool)component2) + { + beamTipTransform = component2.FindChild("BeamTip"); + } + healBeamCurve = buffBeamInstance.GetComponentInChildren(); + } + } + + private void UpdateHealBeamVisuals() + { + float widthMultiplier = beamWidthCurve.Evaluate(base.age / duration); + healBeamCurve.lineRenderer.widthMultiplier = widthMultiplier; + healBeamCurve.v0 = muzzleTransform.forward * 3f; + healBeamCurve.transform.position = muzzleTransform.position; + if ((bool)target) + { + beamTipTransform.position = targetBody.mainHurtBox.transform.position; + } + } + + public override void Update() + { + base.Update(); + UpdateHealBeamVisuals(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((base.fixedAge >= duration || target == null) && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + Util.PlaySound(stopBeamSoundString, base.gameObject); + EntityState.Destroy(buffBeamInstance); + if ((bool)targetBody) + { + targetBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + HurtBoxReference.FromHurtBox(target).Write(writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + HurtBoxReference hurtBoxReference = default(HurtBoxReference); + hurtBoxReference.Read(reader); + target = hurtBoxReference.ResolveGameObject()?.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bell.BellWeapon/ChargeTrioBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Bell.BellWeapon/ChargeTrioBomb.cs new file mode 100644 index 0000000..207841a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bell.BellWeapon/ChargeTrioBomb.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Globalization; +using RoR2; +using RoR2.CharacterAI; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Bell.BellWeapon; + +public class ChargeTrioBomb : BaseState +{ + public static float basePrepDuration; + + public static float baseTimeBetweenPreps; + + public static GameObject preppedBombPrefab; + + public static float baseBarrageDuration; + + public static float baseTimeBetweenBarrages; + + public static GameObject bombProjectilePrefab; + + public static GameObject muzzleflashPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float selfForce; + + private float prepDuration; + + private float timeBetweenPreps; + + private float barrageDuration; + + private float timeBetweenBarrages; + + private ChildLocator childLocator; + + private List preppedBombInstances = new List(); + + private int currentBombIndex; + + private float perProjectileStopwatch; + + public override void OnEnter() + { + base.OnEnter(); + prepDuration = basePrepDuration / attackSpeedStat; + timeBetweenPreps = baseTimeBetweenPreps / attackSpeedStat; + barrageDuration = baseBarrageDuration / attackSpeedStat; + timeBetweenBarrages = baseTimeBetweenBarrages / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + } + } + + private string FindTargetChildStringFromBombIndex() + { + return string.Format(CultureInfo.InvariantCulture, "ProjectilePosition{0}", currentBombIndex); + } + + private Transform FindTargetChildTransformFromBombIndex() + { + string childName = FindTargetChildStringFromBombIndex(); + return childLocator.FindChild(childName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + perProjectileStopwatch += GetDeltaTime(); + if (base.fixedAge < prepDuration) + { + if (perProjectileStopwatch > timeBetweenPreps && currentBombIndex < 3) + { + currentBombIndex++; + perProjectileStopwatch = 0f; + Transform transform = FindTargetChildTransformFromBombIndex(); + if ((bool)transform) + { + GameObject item = Object.Instantiate(preppedBombPrefab, transform); + preppedBombInstances.Add(item); + } + } + } + else if (base.fixedAge < prepDuration + barrageDuration) + { + if (!(perProjectileStopwatch > timeBetweenBarrages) || currentBombIndex <= 0) + { + return; + } + perProjectileStopwatch = 0f; + Ray aimRay = GetAimRay(); + Transform transform2 = FindTargetChildTransformFromBombIndex(); + if ((bool)transform2) + { + if (base.isAuthority) + { + float damage = damageStat * damageCoefficient; + BaseAI component = outer.commonComponents.characterBody.master.GetComponent(); + if ((object)component != null && component.shouldMissFirstOffScreenShot && component.currentEnemy.characterBody.teamComponent.teamIndex == TeamIndex.Player) + { + aimRay.direction = OffScreenMissHelper.ApplyRandomTrajectoryOffset(aimRay.direction); + damage = 0f; + if (currentBombIndex <= 1) + { + component.shouldMissFirstOffScreenShot = false; + } + } + ProjectileManager.instance.FireProjectile(bombProjectilePrefab, transform2.position, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damage, force, Util.CheckRoll(critStat, base.characterBody.master)); + Rigidbody component2 = GetComponent(); + if ((bool)component2) + { + component2.AddForceAtPosition((0f - selfForce) * transform2.forward, transform2.position); + } + } + EffectManager.SimpleMuzzleFlash(muzzleflashPrefab, base.gameObject, FindTargetChildStringFromBombIndex(), transmit: false); + } + currentBombIndex--; + EntityState.Destroy(preppedBombInstances[currentBombIndex]); + } + else if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + foreach (GameObject preppedBombInstance in preppedBombInstances) + { + EntityState.Destroy(preppedBombInstance); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bell/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Bell/DeathState.cs new file mode 100644 index 0000000..3dab3f8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bell/DeathState.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bell; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialEffect; + + public static float initialEffectScale; + + public static float velocityMagnitude; + + public static float explosionForce; + + protected override bool shouldAutoDestroy => false; + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + if ((bool)modelTransform.GetComponent() && (bool)initialEffect) + { + EffectManager.SpawnEffect(initialEffect, new EffectData + { + origin = base.transform.position, + scale = initialEffectScale + }, transmit: false); + } + RagdollController component = modelTransform.GetComponent(); + Rigidbody component2 = GetComponent(); + if ((bool)component && (bool)component2) + { + component.BeginRagdoll(component2.velocity * velocityMagnitude); + } + ExplodeRigidbodiesOnStart component3 = modelTransform.GetComponent(); + if ((bool)component3) + { + component3.force = explosionForce; + component3.enabled = true; + } + } + if ((bool)base.modelLocator) + { + base.modelLocator.autoUpdateModelTransform = false; + } + DestroyBodyAsapServer(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bell/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Bell/SpawnState.cs new file mode 100644 index 0000000..8cf1416 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bell/SpawnState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bell; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bison/Charge.cs b/ilspy_dump/ror2_csproj/EntityStates.Bison/Charge.cs new file mode 100644 index 0000000..be193e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bison/Charge.cs @@ -0,0 +1,181 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.Bison; + +public class Charge : BaseState +{ + public static float chargeDuration; + + public static float chargeMovementSpeedCoefficient; + + public static float turnSpeed; + + public static float turnSmoothTime; + + public static float impactDamageCoefficient; + + public static float impactForce; + + public static float damageCoefficient; + + public static float upwardForceMagnitude; + + public static float awayForceMagnitude; + + public static GameObject hitEffectPrefab; + + public static float overlapResetFrequency; + + public static float overlapSphereRadius; + + public static float selfStunDuration; + + public static float selfStunForce; + + public static string startSoundString; + + public static string endSoundString; + + public static string footstepOverrideSoundString; + + public static string headbuttImpactSound; + + private float stopwatch; + + private float overlapResetStopwatch; + + private Animator animator; + + private Vector3 targetMoveVector; + + private Vector3 targetMoveVectorVelocity; + + private ContactDamage contactDamage; + + private OverlapAttack attack; + + private HitBoxGroup hitboxGroup; + + private ChildLocator childLocator; + + private Transform sphereCheckTransform; + + private string baseFootstepString; + + private static int forwardSpeedParamHash = Animator.StringToHash("forwardSpeed"); + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + childLocator = animator.GetComponent(); + FootstepHandler component = animator.GetComponent(); + if ((bool)component) + { + baseFootstepString = component.baseFootstepString; + component.baseFootstepString = footstepOverrideSoundString; + } + Util.PlaySound(startSoundString, base.gameObject); + PlayCrossfade("Body", "ChargeForward", 0.2f); + ResetOverlapAttack(); + SetSprintEffectActive(active: true); + if ((bool)childLocator) + { + sphereCheckTransform = childLocator.FindChild("SphereCheckTransform"); + } + if (!sphereCheckTransform && (bool)base.characterBody) + { + sphereCheckTransform = base.characterBody.coreTransform; + } + if (!sphereCheckTransform) + { + sphereCheckTransform = base.transform; + } + } + + private void SetSprintEffectActive(bool active) + { + if ((bool)childLocator) + { + childLocator.FindChild("SprintEffect")?.gameObject.SetActive(active); + } + } + + public override void OnExit() + { + base.OnExit(); + base.characterMotor.moveDirection = Vector3.zero; + Util.PlaySound(endSoundString, base.gameObject); + Util.PlaySound("stop_bison_charge_attack_loop", base.gameObject); + SetSprintEffectActive(active: false); + FootstepHandler component = animator.GetComponent(); + if ((bool)component) + { + component.baseFootstepString = baseFootstepString; + } + } + + public override void FixedUpdate() + { + targetMoveVector = Vector3.ProjectOnPlane(Vector3.SmoothDamp(targetMoveVector, base.inputBank.aimDirection, ref targetMoveVectorVelocity, turnSmoothTime, turnSpeed), Vector3.up).normalized; + base.characterDirection.moveVector = targetMoveVector; + Vector3 forward = base.characterDirection.forward; + float value = moveSpeedStat * chargeMovementSpeedCoefficient; + base.characterMotor.moveDirection = forward * chargeMovementSpeedCoefficient; + animator.SetFloat(forwardSpeedParamHash, value); + if (base.isAuthority && attack.Fire()) + { + Util.PlaySound(headbuttImpactSound, base.gameObject); + } + if (overlapResetStopwatch >= 1f / overlapResetFrequency) + { + overlapResetStopwatch -= 1f / overlapResetFrequency; + } + if (base.isAuthority && HGPhysics.DoesOverlapSphere(sphereCheckTransform.position, overlapSphereRadius, LayerIndex.world.mask)) + { + Util.PlaySound(headbuttImpactSound, base.gameObject); + EffectManager.SimpleMuzzleFlash(hitEffectPrefab, base.gameObject, "SphereCheckTransform", transmit: true); + base.healthComponent.TakeDamageForce(forward * selfStunForce, alwaysApply: true); + StunState stunState = new StunState(); + stunState.stunDuration = selfStunDuration; + outer.SetNextState(stunState); + return; + } + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + overlapResetStopwatch += deltaTime; + if (stopwatch > chargeDuration) + { + outer.SetNextStateToMain(); + } + base.FixedUpdate(); + } + + private void ResetOverlapAttack() + { + if (!hitboxGroup) + { + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + hitboxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Charge"); + } + } + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.forceVector = Vector3.up * upwardForceMagnitude; + attack.pushAwayForce = awayForceMagnitude; + attack.hitBoxGroup = hitboxGroup; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bison/Headbutt.cs b/ilspy_dump/ror2_csproj/EntityStates.Bison/Headbutt.cs new file mode 100644 index 0000000..1902f17 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bison/Headbutt.cs @@ -0,0 +1,81 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Bison; + +public class Headbutt : BaseState +{ + public static float baseHeadbuttDuration; + + public static float damageCoefficient; + + public static string attackSoundString; + + public static GameObject hitEffectPrefab; + + public static float upwardForceMagnitude; + + public static float awayForceMagnitude; + + private float headbuttDuration; + + private float stopwatch; + + private OverlapAttack attack; + + private Animator animator; + + private bool hasAttacked; + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + animator = modelTransform.GetComponent(); + headbuttDuration = baseHeadbuttDuration / attackSpeedStat; + Util.PlaySound(attackSoundString, base.gameObject); + PlayCrossfade("Body", "Headbutt", "Headbutt.playbackRate", headbuttDuration, 0.2f); + base.characterMotor.moveDirection = Vector3.zero; + base.characterDirection.moveVector = base.characterDirection.forward; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.forceVector = Vector3.up * upwardForceMagnitude; + attack.pushAwayForce = awayForceMagnitude; + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Headbutt"); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)animator && animator.GetFloat("Headbutt.hitBoxActive") > 0.5f) + { + if (NetworkServer.active) + { + attack.Fire(); + } + if (base.isAuthority && !hasAttacked) + { + hasAttacked = true; + } + } + stopwatch += GetDeltaTime(); + if (stopwatch > headbuttDuration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bison/PrepCharge.cs b/ilspy_dump/ror2_csproj/EntityStates.Bison/PrepCharge.cs new file mode 100644 index 0000000..ecebc5c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bison/PrepCharge.cs @@ -0,0 +1,109 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bison; + +public class PrepCharge : BaseState +{ + public static float basePrepDuration; + + public static string enterSoundString; + + public static GameObject chargeEffectPrefab; + + private float stopwatch; + + private float prepDuration; + + private GameObject chargeEffectInstance; + + private EffectManagerHelper _emh_chargeEffectInstance; + + public override void Reset() + { + base.Reset(); + prepDuration = 0f; + chargeEffectInstance = null; + _emh_chargeEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + prepDuration = basePrepDuration / attackSpeedStat; + base.characterBody.SetAimTimer(prepDuration); + PlayCrossfade("Body", "PrepCharge", "PrepCharge.playbackRate", prepDuration, 0.2f); + Util.PlaySound(enterSoundString, base.gameObject); + Transform modelTransform = GetModelTransform(); + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if (!modelTransform) + { + return; + } + ChildLocator component2 = modelTransform.GetComponent(); + if (!component2) + { + return; + } + Transform transform = component2.FindChild("ChargeIndicator"); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance = _emh_chargeEffectInstance.gameObject; + } + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component3 = chargeEffectInstance.GetComponent(); + if ((bool)component3) + { + component3.newDuration = prepDuration; + } + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeEffectInstance) + { + if (_emh_chargeEffectInstance != null && _emh_chargeEffectInstance.OwningPool != null) + { + _emh_chargeEffectInstance.OwningPool.ReturnObject(_emh_chargeEffectInstance); + } + else + { + EntityState.Destroy(chargeEffectInstance); + } + chargeEffectInstance = null; + _emh_chargeEffectInstance = null; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch > prepDuration && base.isAuthority) + { + outer.SetNextState(new Charge()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Bison/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Bison/SpawnState.cs new file mode 100644 index 0000000..c737c26 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Bison/SpawnState.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Bison; + +public class SpawnState : BaseState +{ + public static GameObject spawnEffectPrefab; + + public static string spawnEffectMuzzle; + + public static float duration; + + public static float snowyOverlayDuration; + + public static Material snowyMaterial; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnEffectMuzzle, transmit: false); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound("Play_bison_idle_graze", base.gameObject); + Util.PlaySound("Play_bison_charge_attack_collide", base.gameObject); + if ((bool)modelTransform) + { + CharacterModel component = modelTransform.GetComponent(); + if ((bool)component && (bool)snowyMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(component.gameObject); + temporaryOverlayInstance.duration = snowyOverlayDuration; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = snowyMaterial; + temporaryOverlayInstance.inspectorCharacterModel = component; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherHaunt/FireRandomProjectiles.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherHaunt/FireRandomProjectiles.cs new file mode 100644 index 0000000..28fc111 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherHaunt/FireRandomProjectiles.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Navigation; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.BrotherHaunt; + +public class FireRandomProjectiles : BaseState +{ + public static GameObject projectilePrefab; + + public static float damageCoefficient; + + public static int initialCharges; + + public static int maximumCharges; + + public static float chargeRechargeDuration; + + public static float chanceToFirePerSecond; + + public static float projectileVerticalOffset; + + private int charges; + + private float chargeTimer; + + public override void OnEnter() + { + base.OnEnter(); + charges = initialCharges; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + chargeTimer -= GetDeltaTime(); + if (chargeTimer <= 0f) + { + chargeTimer = chargeRechargeDuration; + charges = Mathf.Min(charges + 1, maximumCharges); + } + if (Random.value < chanceToFirePerSecond && charges > 0) + { + FireProjectile(); + } + } + } + + private void FireProjectile() + { + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + if ((bool)groundNodes) + { + List activeNodesForHullMaskWithFlagConditions = groundNodes.GetActiveNodesForHullMaskWithFlagConditions(HullMask.Golem, NodeFlags.None, NodeFlags.NoCharacterSpawn); + NodeGraph.NodeIndex nodeIndex = activeNodesForHullMaskWithFlagConditions[Random.Range(0, activeNodesForHullMaskWithFlagConditions.Count)]; + charges--; + groundNodes.GetNodePosition(nodeIndex, out var position); + ProjectileManager.instance.FireProjectile(new FireProjectileInfo + { + projectilePrefab = projectilePrefab, + owner = base.gameObject, + damage = damageStat * damageCoefficient, + position = position + Vector3.up * projectileVerticalOffset, + rotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) + }); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster.Weapon/FireLunarShards.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster.Weapon/FireLunarShards.cs new file mode 100644 index 0000000..1a43407 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster.Weapon/FireLunarShards.cs @@ -0,0 +1,88 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.BrotherMonster.Weapon; + +public class FireLunarShards : BaseSkillState +{ + public static float baseDuration; + + [SerializeField] + public float damageCoefficient; + + public static GameObject projectilePrefab; + + public static float recoilAmplitude; + + public static float spreadBloomValue; + + public static string muzzleString; + + public static GameObject muzzleFlashEffectPrefab; + + public static string fireSound; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public float spreadYawScale; + + [SerializeField] + public float spreadPitchScale; + + private float duration; + + private static int FireLunarShardsStateHash = Animator.StringToHash("FireLunarShards"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + Transform transform = FindModelChild(muzzleString); + if ((bool)transform) + { + aimRay.origin = transform.position; + } + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, maxSpread, spreadYawScale, spreadPitchScale); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = aimRay.origin; + fireProjectileInfo.rotation = Quaternion.LookRotation(aimRay.direction); + fireProjectileInfo.crit = base.characterBody.RollCrit(); + fireProjectileInfo.damage = base.characterBody.damage * damageCoefficient; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.force = 0f; + fireProjectileInfo.useFuseOverride = false; + fireProjectileInfo.useSpeedOverride = false; + fireProjectileInfo.target = null; + fireProjectileInfo.projectilePrefab = projectilePrefab; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + PlayAnimation("Gesture, Additive", FireLunarShardsStateHash); + PlayAnimation("Gesture, Override", FireLunarShardsStateHash); + AddRecoil(-0.4f * recoilAmplitude, -0.8f * recoilAmplitude, -0.3f * recoilAmplitude, 0.3f * recoilAmplitude); + base.characterBody.AddSpreadBloom(spreadBloomValue); + EffectManager.SimpleMuzzleFlash(muzzleFlashEffectPrefab, base.gameObject, muzzleString, transmit: false); + Util.PlaySound(fireSound, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster.Weapon/FireLunarShardsHurt.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster.Weapon/FireLunarShardsHurt.cs new file mode 100644 index 0000000..6292fb1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster.Weapon/FireLunarShardsHurt.cs @@ -0,0 +1,5 @@ +namespace EntityStates.BrotherMonster.Weapon; + +public class FireLunarShardsHurt : FireLunarShards +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/BaseSlideState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/BaseSlideState.cs new file mode 100644 index 0000000..fcc5783 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/BaseSlideState.cs @@ -0,0 +1,93 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class BaseSlideState : BaseState +{ + public static float duration; + + public static AnimationCurve speedCoefficientCurve; + + public static AnimationCurve jumpforwardSpeedCoefficientCurve; + + public static string soundString; + + public static GameObject slideEffectPrefab; + + public static string slideEffectMuzzlestring; + + protected Vector3 slideVector; + + protected Quaternion slideRotation; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundString, base.gameObject); + if ((bool)base.inputBank) + { + _ = (bool)base.characterDirection; + } + if (NetworkServer.active) + { + Util.CleanseBody(base.characterBody, removeDebuffs: true, removeBuffs: false, removeCooldownBuffs: false, removeDots: false, removeStun: false, removeNearbyProjectiles: false); + } + if ((bool)slideEffectPrefab && (bool)base.characterBody) + { + Vector3 position = base.characterBody.corePosition; + Quaternion rotation = Quaternion.identity; + Transform transform = FindModelChild(slideEffectMuzzlestring); + if ((bool)transform) + { + position = transform.position; + } + if ((bool)base.characterDirection) + { + rotation = Util.QuaternionSafeLookRotation(slideRotation * base.characterDirection.forward, Vector3.up); + } + EffectManager.SimpleEffect(slideEffectPrefab, position, rotation, transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + Vector3 vector = Vector3.zero; + if ((bool)base.inputBank && (bool)base.characterDirection) + { + vector = base.characterDirection.forward; + } + if ((bool)base.characterMotor) + { + float num = speedCoefficientCurve.Evaluate(base.fixedAge / duration); + base.characterMotor.rootMotion += slideRotation * (num * moveSpeedStat * vector * GetDeltaTime()); + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + PlayImpactAnimation(); + } + base.OnExit(); + } + + private void PlayImpactAnimation() + { + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/EnterSkyLeap.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/EnterSkyLeap.cs new file mode 100644 index 0000000..13e60d5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/EnterSkyLeap.cs @@ -0,0 +1,44 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class EnterSkyLeap : BaseState +{ + public static float baseDuration; + + public static string soundString; + + private float duration; + + private static int EnterSkyLeapStateHash = Animator.StringToHash("EnterSkyLeap"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + private static int SkyLeapParamHash = Animator.StringToHash("SkyLeap.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(soundString, base.gameObject); + PlayAnimation("Body", EnterSkyLeapStateHash, SkyLeapParamHash, duration); + PlayAnimation("FullBody Override", BufferEmptyStateHash); + base.characterDirection.moveVector = base.characterDirection.forward; + base.characterBody.AddTimedBuff(RoR2Content.Buffs.ArmorBoost, baseDuration); + AimAnimator aimAnimator = GetAimAnimator(); + if ((bool)aimAnimator) + { + aimAnimator.enabled = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new HoldSkyLeap()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/ExitSkyLeap.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/ExitSkyLeap.cs new file mode 100644 index 0000000..95598ed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/ExitSkyLeap.cs @@ -0,0 +1,123 @@ +using System; +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class ExitSkyLeap : BaseState +{ + public static float baseDuration; + + public static float baseDurationUntilRecastInterrupt; + + public static string soundString; + + public static GameObject waveProjectilePrefab; + + public static int waveProjectileCount; + + public static float waveProjectileDamageCoefficient; + + public static float waveProjectileForce; + + public static float recastChance; + + public static int cloneCount; + + public static int cloneDuration; + + public static SkillDef replacementSkillDef; + + private float duration; + + private float durationUntilRecastInterrupt; + + private bool recast; + + private static int ExitSkyLeapStateHash = Animator.StringToHash("ExitSkyLeap"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + private static int SkyLeapParamHash = Animator.StringToHash("SkyLeap.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(soundString, base.gameObject); + PlayAnimation("Body", ExitSkyLeapStateHash, SkyLeapParamHash, duration); + PlayAnimation("FullBody Override", BufferEmptyStateHash); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.ArmorBoost, baseDuration); + AimAnimator aimAnimator = GetAimAnimator(); + if ((bool)aimAnimator) + { + aimAnimator.enabled = true; + } + if (base.isAuthority) + { + FireRingAuthority(); + } + if (!PhaseCounter.instance || PhaseCounter.instance.phase != 3) + { + return; + } + if (UnityEngine.Random.value < recastChance) + { + recast = true; + } + for (int i = 0; i < cloneCount; i++) + { + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscBrotherGlass"), new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Approximate, + minDistance = 3f, + maxDistance = 20f, + spawnOnTarget = base.gameObject.transform + }, RoR2Application.rng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult spawnResult) + { + spawnResult.spawnedInstance.GetComponent().GiveItem(RoR2Content.Items.HealthDecay, cloneDuration); + }); + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + } + GenericSkill genericSkill = (base.skillLocator ? base.skillLocator.special : null); + if ((bool)genericSkill) + { + genericSkill.SetSkillOverride(outer, UltChannelState.replacementSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + } + + private void FireRingAuthority() + { + float num = 360f / (float)waveProjectileCount; + Vector3 vector = Vector3.ProjectOnPlane(base.inputBank.aimDirection, Vector3.up); + Vector3 footPosition = base.characterBody.footPosition; + for (int i = 0; i < waveProjectileCount; i++) + { + Vector3 forward = Quaternion.AngleAxis(num * (float)i, Vector3.up) * vector; + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(waveProjectilePrefab, footPosition, Util.QuaternionSafeLookRotation(forward), base.gameObject, base.characterBody.damage * waveProjectileDamageCoefficient, waveProjectileForce, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (recast && base.fixedAge > baseDurationUntilRecastInterrupt) + { + outer.SetNextState(new EnterSkyLeap()); + } + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/FistSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/FistSlam.cs new file mode 100644 index 0000000..71afdf6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/FistSlam.cs @@ -0,0 +1,155 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class FistSlam : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float upwardForce; + + public static float radius = 3f; + + public static string attackSoundString; + + public static string muzzleString; + + public static float healthCostFraction; + + public static GameObject chargeEffectPrefab; + + public static GameObject slamImpactEffect; + + public static GameObject waveProjectilePrefab; + + public static int waveProjectileCount; + + public static float waveProjectileDamageCoefficient; + + public static float waveProjectileForce; + + private BlastAttack attack; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + private float duration; + + private GameObject chargeInstance; + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("FullBody Override", "FistSlam", "FistSlam.playbackRate", duration, 0.1f); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + } + Transform transform = FindModelChild("MuzzleRight"); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration / 2.8f; + } + } + } + + public override void OnExit() + { + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + PlayAnimation("FullBody Override", BufferEmptyStateHash); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("fist.hitBoxActive") > 0.5f && !hasAttacked) + { + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + EffectManager.SimpleMuzzleFlash(slamImpactEffect, base.gameObject, muzzleString, transmit: false); + if (NetworkServer.active && (bool)base.healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal | DamageType.BypassArmor; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + if (base.isAuthority) + { + if ((bool)modelTransform) + { + Transform transform = FindModelChild(muzzleString); + if ((bool)transform) + { + attack = new BlastAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * damageCoefficient; + attack.baseForce = forceMagnitude; + attack.position = transform.position; + attack.radius = radius; + attack.bonusForce = new Vector3(0f, upwardForce, 0f); + attack.Fire(); + } + } + float num = 360f / (float)waveProjectileCount; + Vector3 vector = Vector3.ProjectOnPlane(base.inputBank.aimDirection, Vector3.up); + Vector3 footPosition = base.characterBody.footPosition; + for (int i = 0; i < waveProjectileCount; i++) + { + Vector3 forward = Quaternion.AngleAxis(num * (float)i, Vector3.up) * vector; + ProjectileManager.instance.FireProjectile(waveProjectilePrefab, footPosition, Util.QuaternionSafeLookRotation(forward), base.gameObject, base.characterBody.damage * waveProjectileDamageCoefficient, waveProjectileForce, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + } + hasAttacked = true; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/HoldSkyLeap.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/HoldSkyLeap.cs new file mode 100644 index 0000000..e2a4094 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/HoldSkyLeap.cs @@ -0,0 +1,81 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class HoldSkyLeap : BaseState +{ + public static float duration; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private int originalLayer; + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + Util.PlaySound("Play_moonBrother_phaseJump_land_preWhoosh", base.gameObject); + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + if (!SceneInfo.instance) + { + return; + } + ChildLocator component = SceneInfo.instance.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("CenterOfArena"); + if ((bool)transform) + { + base.characterMotor.Motor.SetPositionAndRotation(transform.position, Quaternion.identity); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new ExitSkyLeap()); + } + } + + public override void OnExit() + { + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/InstantDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/InstantDeathState.cs new file mode 100644 index 0000000..ad815ef --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/InstantDeathState.cs @@ -0,0 +1,28 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class InstantDeathState : GenericCharacterDeath +{ + public static GameObject deathEffectPrefab; + + protected override bool shouldAutoDestroy => false; + + public override void OnEnter() + { + base.OnEnter(); + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + + protected override void CreateDeathEffects() + { + base.CreateDeathEffects(); + EffectManager.SimpleMuzzleFlash(deathEffectPrefab, base.gameObject, "MuzzleCenter", transmit: false); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SkyLeapDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SkyLeapDeathState.cs new file mode 100644 index 0000000..0f0e061 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SkyLeapDeathState.cs @@ -0,0 +1,47 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class SkyLeapDeathState : GenericCharacterDeath +{ + public static float baseDuration; + + private float duration; + + private static int SkyLeapStateHash = Animator.StringToHash("EnterSkyLeap"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + private static int SkyLeapParamHash = Animator.StringToHash("SkyLeap.playbackRate"); + + protected override bool shouldAutoDestroy => false; + + public override void OnEnter() + { + duration = baseDuration / attackSpeedStat; + base.OnEnter(); + } + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayAnimation("Body", SkyLeapStateHash, SkyLeapParamHash, duration); + PlayAnimation("FullBody Override", BufferEmptyStateHash); + base.characterDirection.moveVector = base.characterDirection.forward; + AimAnimator aimAnimator = GetAimAnimator(); + if ((bool)aimAnimator) + { + aimAnimator.enabled = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + DestroyBodyAsapServer(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SkySpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SkySpawnState.cs new file mode 100644 index 0000000..e795461 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SkySpawnState.cs @@ -0,0 +1,34 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SkySpawnState : BaseState +{ + public static float duration; + + public static string soundString; + + private static int ExitSkyLeapStateHash = Animator.StringToHash("ExitSkyLeap"); + + private static int BufferEmptyLeapStateHash = Animator.StringToHash("BufferEmpty"); + + private static int SkyLeapParamHash = Animator.StringToHash("SkyLeap.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", ExitSkyLeapStateHash, SkyLeapParamHash, duration); + PlayAnimation("FullBody Override", BufferEmptyLeapStateHash); + Util.PlaySound(soundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideBackwardState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideBackwardState.cs new file mode 100644 index 0000000..4b2175d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideBackwardState.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SlideBackwardState : BaseSlideState +{ + public override void OnEnter() + { + slideRotation = Quaternion.AngleAxis(-180f, Vector3.up); + base.OnEnter(); + PlayCrossfade("FullBody Override", "SlideBackward", "Slide.playbackRate", BaseSlideState.duration, 0.05f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideForwardState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideForwardState.cs new file mode 100644 index 0000000..e9850b6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideForwardState.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SlideForwardState : BaseSlideState +{ + public override void OnEnter() + { + slideRotation = Quaternion.identity; + base.OnEnter(); + PlayCrossfade("FullBody Override", "SlideForward", "Slide.playbackRate", BaseSlideState.duration, 0.05f); + PlayCrossfade("Body", "Run", 0.05f); + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideIntroState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideIntroState.cs new file mode 100644 index 0000000..d474de6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideIntroState.cs @@ -0,0 +1,51 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SlideIntroState : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + bool flag = false; + if ((bool)base.inputBank && base.isAuthority) + { + Vector3 normalized = ((base.inputBank.moveVector == Vector3.zero) ? base.characterDirection.forward : base.inputBank.moveVector).normalized; + Vector3 forward = base.characterDirection.forward; + Vector3 rhs = Vector3.Cross(Vector3.up, forward); + float num = Vector3.Dot(normalized, forward); + float num2 = Vector3.Dot(normalized, rhs); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.inputBank.aimDirection; + } + if (Mathf.Abs(num2) > Mathf.Abs(num)) + { + if (num2 <= 0f) + { + flag = true; + outer.SetNextState(new SlideLeftState()); + } + else + { + flag = true; + outer.SetNextState(new SlideRightState()); + } + } + else if (num <= 0f) + { + flag = true; + outer.SetNextState(new SlideBackwardState()); + } + else + { + flag = true; + outer.SetNextState(new SlideForwardState()); + } + } + if (!flag) + { + outer.SetNextState(new SlideForwardState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideLeftState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideLeftState.cs new file mode 100644 index 0000000..937648f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideLeftState.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SlideLeftState : BaseSlideState +{ + public override void OnEnter() + { + slideRotation = Quaternion.AngleAxis(-90f, Vector3.up); + base.OnEnter(); + PlayCrossfade("FullBody Override", "SlideLeft", "Slide.playbackRate", BaseSlideState.duration, 0.05f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideRightState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideRightState.cs new file mode 100644 index 0000000..bcfacda --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SlideRightState.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SlideRightState : BaseSlideState +{ + public override void OnEnter() + { + slideRotation = Quaternion.AngleAxis(90f, Vector3.up); + base.OnEnter(); + PlayCrossfade("FullBody Override", "SlideRight", "Slide.playbackRate", BaseSlideState.duration, 0.05f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellBaseState.cs new file mode 100644 index 0000000..8667fef --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellBaseState.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class SpellBaseState : BaseState +{ + protected ItemStealController itemStealController; + + protected GameObject hammerRendererObject; + + protected virtual bool DisplayWeapon => false; + + public override void OnEnter() + { + base.OnEnter(); + FindItemStealer(); + if (NetworkServer.active && !itemStealController) + { + InitItemStealer(); + } + hammerRendererObject = FindModelChild("HammerRenderer").gameObject; + if ((bool)hammerRendererObject) + { + hammerRendererObject.SetActive(DisplayWeapon); + } + } + + public override void OnExit() + { + if ((bool)hammerRendererObject) + { + hammerRendererObject.SetActive(value: false); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + FindItemStealer(); + } + + private void FindItemStealer() + { + if ((bool)itemStealController) + { + return; + } + List list = new List(); + NetworkedBodyAttachment.FindBodyAttachments(base.characterBody, list); + foreach (NetworkedBodyAttachment item in list) + { + itemStealController = item.GetComponent(); + if ((bool)itemStealController) + { + break; + } + } + } + + private void InitItemStealer() + { + if (NetworkServer.active && itemStealController == null) + { + GameObject gameObject = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/ItemStealController"), base.transform.position, Quaternion.identity); + itemStealController = gameObject.GetComponent(); + itemStealController.itemLendFilter = ItemStealController.BrotherItemFilter; + gameObject.GetComponent().AttachToGameObjectAndSpawn(base.gameObject); + base.gameObject.GetComponent().itemStealController = itemStealController; + NetworkServer.Spawn(gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelEnterState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelEnterState.cs new file mode 100644 index 0000000..494fbcc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelEnterState.cs @@ -0,0 +1,66 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SpellChannelEnterState : SpellBaseState +{ + public static GameObject channelBeginEffectPrefab; + + public static float duration; + + private Transform trueDeathEffect; + + private static int SpellChannerEnterStateHash = Animator.StringToHash("SpellChannelEnter"); + + private static int SpellChannelEnterParamHash = Animator.StringToHash("SpellChannelEnter.playbackRate"); + + protected override bool DisplayWeapon => false; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpellChannerEnterStateHash, SpellChannelEnterParamHash, duration); + Util.PlaySound("Play_moonBrother_phase4_transition", base.gameObject); + trueDeathEffect = FindModelChild("TrueDeathEffect"); + if ((bool)trueDeathEffect) + { + trueDeathEffect.gameObject.SetActive(value: true); + trueDeathEffect.GetComponent().newDuration = 10f; + } + HurtBoxGroup component = GetModelTransform().GetComponent(); + if ((bool)component) + { + int hurtBoxesDeactivatorCounter = component.hurtBoxesDeactivatorCounter + 1; + component.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new SpellChannelState()); + } + } + + public override void OnExit() + { + HurtBoxGroup component = GetModelTransform().GetComponent(); + if ((bool)component) + { + int hurtBoxesDeactivatorCounter = component.hurtBoxesDeactivatorCounter - 1; + component.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)channelBeginEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(channelBeginEffectPrefab, base.gameObject, "SpellChannel", transmit: false); + } + if ((bool)trueDeathEffect) + { + trueDeathEffect.gameObject.SetActive(value: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelExitState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelExitState.cs new file mode 100644 index 0000000..28dc59f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelExitState.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class SpellChannelExitState : SpellBaseState +{ + public static float lendInterval; + + public static float duration; + + public static GameObject channelFinishEffectPrefab; + + private static int SpellChannelExitStateHash = Animator.StringToHash("SpellChannelExit"); + + private static int SpellChannelExitParamHash = Animator.StringToHash("SpellChannelExit.playbackRate"); + + protected override bool DisplayWeapon => false; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpellChannelExitStateHash, SpellChannelExitParamHash, duration); + if (NetworkServer.active && (bool)itemStealController) + { + itemStealController.stealInterval = lendInterval; + itemStealController.LendImmediately(base.characterBody.inventory); + } + if ((bool)channelFinishEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(channelFinishEffectPrefab, base.gameObject, "SpellChannel", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + SetStateOnHurt component = GetComponent(); + if ((bool)component) + { + component.canBeFrozen = true; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelState.cs new file mode 100644 index 0000000..a3b324c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SpellChannelState.cs @@ -0,0 +1,98 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class SpellChannelState : SpellBaseState +{ + public static float stealInterval; + + public static float delayBeforeBeginningSteal; + + public static float maxDuration; + + public static GameObject channelEffectPrefab; + + private bool hasBegunSteal; + + private GameObject channelEffectInstance; + + private Transform spellChannelChildTransform; + + private bool hasSubscribedToStealFinish; + + private static int SpellChannelStateHash = Animator.StringToHash("SpellChannel"); + + protected override bool DisplayWeapon => false; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpellChannelStateHash); + Util.PlaySound("Play_moonBrother_phase4_itemSuck_start", base.gameObject); + spellChannelChildTransform = FindModelChild("SpellChannel"); + if ((bool)spellChannelChildTransform) + { + channelEffectInstance = Object.Instantiate(channelEffectPrefab, spellChannelChildTransform.position, Quaternion.identity, spellChannelChildTransform); + } + base.characterBody.AddBuff(RoR2Content.Buffs.Immune); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!itemStealController) + { + return; + } + if (!hasSubscribedToStealFinish && base.isAuthority) + { + hasSubscribedToStealFinish = true; + if (NetworkServer.active) + { + itemStealController.onStealFinishServer.AddListener(OnStealEndAuthority); + } + else + { + itemStealController.onStealFinishClient += OnStealEndAuthority; + } + } + if (NetworkServer.active && base.fixedAge > delayBeforeBeginningSteal && !hasBegunSteal) + { + hasBegunSteal = true; + itemStealController.stealInterval = stealInterval; + TeamIndex teamIndex = GetTeam(); + itemStealController.StartSteal((CharacterMaster characterMaster) => characterMaster.teamIndex != teamIndex && characterMaster.hasBody); + } + if (base.isAuthority && base.fixedAge > delayBeforeBeginningSteal + maxDuration) + { + outer.SetNextState(new SpellChannelExitState()); + } + if ((bool)spellChannelChildTransform) + { + itemStealController.transform.position = spellChannelChildTransform.position; + } + } + + public override void OnExit() + { + if ((bool)itemStealController && hasSubscribedToStealFinish) + { + itemStealController.onStealFinishServer.RemoveListener(OnStealEndAuthority); + itemStealController.onStealFinishClient -= OnStealEndAuthority; + } + if ((bool)channelEffectInstance) + { + EntityState.Destroy(channelEffectInstance); + } + Util.PlaySound("Play_moonBrother_phase4_itemSuck_end", base.gameObject); + base.characterBody.RemoveBuff(RoR2Content.Buffs.Immune); + base.OnExit(); + } + + private void OnStealEndAuthority() + { + outer.SetNextState(new SpellChannelExitState()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SprintBash.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SprintBash.cs new file mode 100644 index 0000000..0324a33 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/SprintBash.cs @@ -0,0 +1,57 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class SprintBash : BasicMeleeAttack +{ + public static float durationBeforePriorityReduces; + + protected override void PlayAnimation() + { + PlayCrossfade("FullBody Override", "SprintBash", "SprintBash.playbackRate", duration, 0.05f); + } + + public override void OnEnter() + { + base.OnEnter(); + AimAnimator aimAnimator = GetAimAnimator(); + if ((bool)aimAnimator) + { + aimAnimator.enabled = true; + } + if ((bool)base.characterDirection) + { + base.characterDirection.forward = base.inputBank.aimDirection; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)base.inputBank && (bool)base.skillLocator && base.skillLocator.utility.IsReady() && base.inputBank.skill3.justPressed) + { + base.skillLocator.utility.ExecuteIfReady(); + } + } + + public override void OnExit() + { + Transform transform = FindModelChild("SpinnyFX"); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + PlayCrossfade("FullBody Override", "BufferEmpty", 0.1f); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge > durationBeforePriorityReduces)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerBaseState.cs new file mode 100644 index 0000000..c5aa5ea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerBaseState.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class StaggerBaseState : BaseState +{ + [SerializeField] + public float duration; + + public virtual EntityState nextState => null; + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerEnter.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerEnter.cs new file mode 100644 index 0000000..ec8ff58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerEnter.cs @@ -0,0 +1,27 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class StaggerEnter : StaggerBaseState +{ + public static GameObject effectPrefab; + + public static string effectMuzzleString; + + private static int StaggerEnterStateHash = Animator.StringToHash("StaggerEnter"); + + private static int StaggerParamHash = Animator.StringToHash("Stagger.playbackRate"); + + public override EntityState nextState => new StaggerLoop(); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", StaggerEnterStateHash, StaggerParamHash, duration); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, effectMuzzleString, transmit: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerExit.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerExit.cs new file mode 100644 index 0000000..f662211 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerExit.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class StaggerExit : StaggerBaseState +{ + private static int StaggerExitStateHash = Animator.StringToHash("StaggerExit"); + + private static int StaggerParamHash = Animator.StringToHash("Stagger.playbackRate"); + + public override EntityState nextState => new GenericCharacterMain(); + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", StaggerExitStateHash, StaggerParamHash, duration, 0.1f); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerLoop.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerLoop.cs new file mode 100644 index 0000000..1d6eb59 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/StaggerLoop.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class StaggerLoop : StaggerBaseState +{ + private static int StaggerLoopStateHash = Animator.StringToHash("StaggerLoop"); + + public override EntityState nextState => new StaggerExit(); + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "StaggerLoop", 0.2f); + PlayCrossfade("Body", StaggerLoopStateHash, 0.2f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/ThroneSpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/ThroneSpawnState.cs new file mode 100644 index 0000000..fec6a39 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/ThroneSpawnState.cs @@ -0,0 +1,52 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class ThroneSpawnState : BaseState +{ + public static GameObject spawnEffectPrefab; + + public static string muzzleString; + + public static float initialDelay; + + public static float duration; + + private bool hasPlayedAnimation; + + private static int ThroneStateHash = Animator.StringToHash("Throne"); + + private static int ThroneToIdleStateHash = Animator.StringToHash("ThroneToIdle"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + private static int ThroneToIdleParamHash = Animator.StringToHash("ThroneToIdle.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", ThroneStateHash); + PlayAnimation("FullBody Override", BufferEmptyStateHash); + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + + private void PlayAnimation() + { + hasPlayedAnimation = true; + PlayAnimation("Body", ThroneToIdleStateHash, ThroneToIdleParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > initialDelay && !hasPlayedAnimation) + { + PlayAnimation(); + } + if (base.fixedAge > initialDelay + duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/TrueDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/TrueDeathState.cs new file mode 100644 index 0000000..e43cc29 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/TrueDeathState.cs @@ -0,0 +1,73 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.BrotherMonster; + +public class TrueDeathState : GenericCharacterDeath +{ + public static float durationBeforeDissolving; + + public static float dissolveDuration; + + public static GameObject deathEffectPrefab; + + private static int TrueDeathStateHash = Animator.StringToHash("TrueDeath"); + + private bool dissolving; + + protected override bool shouldAutoDestroy => base.fixedAge > durationBeforeDissolving + dissolveDuration + 1f; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + Util.CleanseBody(base.characterBody, removeDebuffs: true, removeBuffs: true, removeCooldownBuffs: true, removeDots: true, removeStun: false, removeNearbyProjectiles: false); + ReturnStolenItemsOnGettingHit component = GetComponent(); + if ((bool)component && (bool)component.itemStealController) + { + EntityState.Destroy(component.itemStealController.gameObject); + } + } + } + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayAnimation("FullBody Override", TrueDeathStateHash); + base.characterDirection.moveVector = base.characterDirection.forward; + EffectManager.SimpleMuzzleFlash(deathEffectPrefab, base.gameObject, "MuzzleCenter", transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= durationBeforeDissolving) + { + Dissolve(); + } + } + + private void Dissolve() + { + if (!dissolving) + { + dissolving = true; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + modelTransform.gameObject.GetComponent(); + PrintController component = base.modelLocator.modelTransform.gameObject.GetComponent(); + component.enabled = false; + component.printTime = dissolveDuration; + component.enabled = true; + } + Transform transform = FindModelChild("TrueDeathEffect"); + if ((bool)transform) + { + transform.gameObject.SetActive(value: true); + transform.GetComponent().newDuration = dissolveDuration; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltChannelState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltChannelState.cs new file mode 100644 index 0000000..e489252 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltChannelState.cs @@ -0,0 +1,96 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class UltChannelState : BaseState +{ + public static GameObject waveProjectileLeftPrefab; + + public static GameObject waveProjectileRightPrefab; + + public static int waveProjectileCount; + + public static float waveProjectileDamageCoefficient; + + public static float waveProjectileForce; + + public static int totalWaves; + + public static float maxDuration; + + public static GameObject channelBeginMuzzleflashEffectPrefab; + + public static GameObject channelEffectPrefab; + + public static string enterSoundString; + + public static string exitSoundString; + + private GameObject channelEffectInstance; + + public static SkillDef replacementSkillDef; + + private int wavesFired; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + Transform transform = FindModelChild("MuzzleUlt"); + if ((bool)transform && (bool)channelEffectPrefab) + { + channelEffectInstance = Object.Instantiate(channelEffectPrefab, transform.position, Quaternion.identity, transform); + } + if ((bool)channelBeginMuzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(channelBeginMuzzleflashEffectPrefab, base.gameObject, "MuzzleUlt", transmit: false); + } + } + + private void FireWave() + { + wavesFired++; + float num = 360f / (float)waveProjectileCount; + Vector3 normalized = Vector3.ProjectOnPlane(Random.onUnitSphere, Vector3.up).normalized; + Vector3 footPosition = base.characterBody.footPosition; + GameObject prefab = waveProjectileLeftPrefab; + if (Random.value <= 0.5f) + { + prefab = waveProjectileRightPrefab; + } + for (int i = 0; i < waveProjectileCount; i++) + { + Vector3 forward = Quaternion.AngleAxis(num * (float)i, Vector3.up) * normalized; + ProjectileManager.instance.FireProjectile(prefab, footPosition, Util.QuaternionSafeLookRotation(forward), base.gameObject, base.characterBody.damage * waveProjectileDamageCoefficient, waveProjectileForce, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (Mathf.CeilToInt(base.fixedAge / maxDuration * (float)totalWaves) > wavesFired) + { + FireWave(); + } + if (base.fixedAge > maxDuration) + { + outer.SetNextState(new UltExitState()); + } + } + } + + public override void OnExit() + { + Util.PlaySound(exitSoundString, base.gameObject); + if ((bool)channelEffectInstance) + { + EntityState.Destroy(channelEffectInstance); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltEnterState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltEnterState.cs new file mode 100644 index 0000000..762134b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltEnterState.cs @@ -0,0 +1,26 @@ +using RoR2; + +namespace EntityStates.BrotherMonster; + +public class UltEnterState : BaseState +{ + public static string soundString; + + public static float duration; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "UltEnter", "Ult.playbackRate", duration, 0.1f); + Util.PlaySound(soundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new UltChannelState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltExitState.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltExitState.cs new file mode 100644 index 0000000..90ddd97 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/UltExitState.cs @@ -0,0 +1,49 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class UltExitState : BaseState +{ + public static float lendInterval; + + public static float duration; + + public static string soundString; + + public static GameObject channelFinishEffectPrefab; + + private static int UltExitStateHash = Animator.StringToHash("UltExit"); + + private static int UltParamHash = Animator.StringToHash("Ult.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", UltExitStateHash, UltParamHash, duration); + Util.PlaySound(soundString, base.gameObject); + if ((bool)channelFinishEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(channelFinishEffectPrefab, base.gameObject, "MuzzleUlt", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + GenericSkill genericSkill = (base.skillLocator ? base.skillLocator.special : null); + if ((bool)genericSkill) + { + genericSkill.UnsetSkillOverride(outer, UltChannelState.replacementSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/WeaponSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/WeaponSlam.cs new file mode 100644 index 0000000..941f310 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.BrotherMonster/WeaponSlam.cs @@ -0,0 +1,179 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.BrotherMonster; + +public class WeaponSlam : BaseState +{ + public static float duration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float upwardForce; + + public static float radius = 3f; + + public static string attackSoundString; + + public static string muzzleString; + + public static GameObject slamImpactEffect; + + public static float durationBeforePriorityReduces; + + public static GameObject waveProjectilePrefab; + + public static float waveProjectileArc; + + public static int waveProjectileCount; + + public static float waveProjectileDamageCoefficient; + + public static float waveProjectileForce; + + public static float weaponDamageCoefficient; + + public static float weaponForce; + + public static GameObject pillarProjectilePrefab; + + public static float pillarDamageCoefficient; + + public static GameObject weaponHitEffectPrefab; + + public static NetworkSoundEventDef weaponImpactSound; + + private BlastAttack blastAttack; + + private OverlapAttack weaponAttack; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasDoneBlastAttack; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("FullBody Override", "WeaponSlam", "WeaponSlam.playbackRate", duration, 0.1f); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + } + if (base.isAuthority) + { + weaponAttack = new OverlapAttack + { + attacker = base.gameObject, + damage = damageCoefficient * damageStat, + damageColorIndex = DamageColorIndex.Default, + damageType = DamageType.Generic, + hitEffectPrefab = weaponHitEffectPrefab, + hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "WeaponBig"), + impactSound = weaponImpactSound.index, + inflictor = base.gameObject, + procChainMask = default(ProcChainMask), + pushAwayForce = weaponForce, + procCoefficient = 1f, + teamIndex = GetTeam() + }; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)base.inputBank && (bool)base.skillLocator && base.skillLocator.utility.IsReady() && base.inputBank.skill3.justPressed) + { + base.skillLocator.utility.ExecuteIfReady(); + return; + } + if ((bool)modelAnimator) + { + if (base.isAuthority && modelAnimator.GetFloat("weapon.hitBoxActive") > 0.5f) + { + weaponAttack.Fire(); + } + if (modelAnimator.GetFloat("blast.hitBoxActive") > 0.5f && !hasDoneBlastAttack) + { + hasDoneBlastAttack = true; + EffectManager.SimpleMuzzleFlash(slamImpactEffect, base.gameObject, muzzleString, transmit: false); + if (base.isAuthority) + { + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)modelTransform) + { + Transform transform = FindModelChild(muzzleString); + if ((bool)transform) + { + blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = forceMagnitude; + blastAttack.position = transform.position; + blastAttack.radius = radius; + blastAttack.bonusForce = new Vector3(0f, upwardForce, 0f); + blastAttack.Fire(); + } + } + if ((bool)PhaseCounter.instance && PhaseCounter.instance.phase == 3) + { + Transform transform2 = FindModelChild(muzzleString); + float num = waveProjectileArc / (float)waveProjectileCount; + Vector3 vector = Vector3.ProjectOnPlane(base.characterDirection.forward, Vector3.up); + Vector3 position = base.characterBody.footPosition; + if ((bool)transform2) + { + position = transform2.position; + } + for (int i = 0; i < waveProjectileCount; i++) + { + Vector3 forward = Quaternion.AngleAxis(num * ((float)i - (float)waveProjectileCount / 2f), Vector3.up) * vector; + ProjectileManager.instance.FireProjectile(waveProjectilePrefab, position, Util.QuaternionSafeLookRotation(forward), base.gameObject, base.characterBody.damage * waveProjectileDamageCoefficient, waveProjectileForce, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + ProjectileManager.instance.FireProjectile(pillarProjectilePrefab, position, Quaternion.identity, base.gameObject, base.characterBody.damage * pillarDamageCoefficient, 0f, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + } + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge > durationBeforePriorityReduces)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike1.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike1.cs new file mode 100644 index 0000000..5e573d4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike1.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class CallAirstrike1 : CallAirstrikeBase +{ + private static int CallAirstrike1StateHash = Animator.StringToHash("CallAirstrike1"); + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void OnExit() + { + PlayAnimation("Gesture, Override", CallAirstrike1StateHash); + PlayAnimation("Gesture, Additive", CallAirstrike1StateHash); + AddRecoil(0f, 0f, -1f, -1f); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike2.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike2.cs new file mode 100644 index 0000000..333d37a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike2.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class CallAirstrike2 : CallAirstrikeBase +{ + private static int CallAirstrike2StateHash = Animator.StringToHash("CallAirstrike2"); + + public override void OnExit() + { + PlayAnimation("Gesture, Override", CallAirstrike2StateHash); + PlayAnimation("Gesture, Additive", CallAirstrike2StateHash); + AddRecoil(0f, 0f, 1f, 1f); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike3.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike3.cs new file mode 100644 index 0000000..1a11abf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrike3.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class CallAirstrike3 : CallAirstrikeBase +{ + private static int CallAirstrike3StateHash = Animator.StringToHash("CallAirstrike3"); + + public override void OnExit() + { + PlayAnimation("Gesture, Override", CallAirstrike3StateHash); + AddRecoil(-2f, -2f, -0.5f, 0.5f); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeAlt.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeAlt.cs new file mode 100644 index 0000000..2341ef3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeAlt.cs @@ -0,0 +1,26 @@ +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class CallAirstrikeAlt : CallAirstrikeBase +{ + [SerializeField] + public float projectileForce; + + private static int CallAirstrike3StateHash = Animator.StringToHash("CallAirstrike3"); + + public override void OnExit() + { + PlayAnimation("Gesture, Override", CallAirstrike3StateHash); + PlayAnimation("Gesture, Additive", CallAirstrike3StateHash); + AddRecoil(-2f, -2f, -0.5f, 0.5f); + base.OnExit(); + } + + protected override void ModifyProjectile(ref FireProjectileInfo fireProjectileInfo) + { + base.ModifyProjectile(ref fireProjectileInfo); + fireProjectileInfo.force = projectileForce; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeAltEnter.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeAltEnter.cs new file mode 100644 index 0000000..b5667a5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeAltEnter.cs @@ -0,0 +1,18 @@ +namespace EntityStates.Captain.Weapon; + +public class CallAirstrikeAltEnter : BaseSkillState +{ + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + outer.SetNextState(new CallAirstrikeAlt()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeBase.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeBase.cs new file mode 100644 index 0000000..612e44e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeBase.cs @@ -0,0 +1,61 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class CallAirstrikeBase : AimThrowableBase +{ + [SerializeField] + public float airstrikeRadius; + + [SerializeField] + public float bloom; + + public static GameObject muzzleFlashEffect; + + public static string muzzleString; + + public static string fireAirstrikeSoundString; + + public override void OnEnter() + { + base.OnEnter(); + base.characterBody.SetSpreadBloom(bloom); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(4f); + } + + public override void OnExit() + { + Util.PlaySound(fireAirstrikeSoundString, base.gameObject); + base.OnExit(); + } + + protected override void ModifyProjectile(ref FireProjectileInfo fireProjectileInfo) + { + base.ModifyProjectile(ref fireProjectileInfo); + fireProjectileInfo.position = currentTrajectoryInfo.hitPoint; + fireProjectileInfo.rotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f); + fireProjectileInfo.speedOverride = 0f; + } + + protected override bool KeyIsDown() + { + return base.inputBank.skill1.down; + } + + protected override EntityState PickNextState() + { + return new Idle(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeEnter.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeEnter.cs new file mode 100644 index 0000000..fbfc699 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallAirstrikeEnter.cs @@ -0,0 +1,27 @@ +namespace EntityStates.Captain.Weapon; + +public class CallAirstrikeEnter : BaseSkillState +{ + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + switch (base.activatorSkillSlot.stock) + { + case 2: + outer.SetNextState(new CallAirstrike1()); + break; + case 1: + outer.SetNextState(new CallAirstrike2()); + break; + case 0: + outer.SetNextState(new CallAirstrike3()); + break; + default: + outer.SetNextState(new CallAirstrike1()); + break; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropBase.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropBase.cs new file mode 100644 index 0000000..1f0e40b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropBase.cs @@ -0,0 +1,107 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropBase : BaseSkillState +{ + [SerializeField] + public GameObject muzzleflashEffect; + + [SerializeField] + public GameObject supplyDropPrefab; + + public static string muzzleString; + + public static float baseDuration; + + public static float impactDamageCoefficient; + + public static float impactDamageForce; + + public SetupSupplyDrop.PlacementInfo placementInfo; + + private static int CallSupplyDropStateHash = Animator.StringToHash("CallSupplyDrop"); + + private static int CallSupplyDropParamHash = Animator.StringToHash("CallSupplyDrop.playbackRate"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + private float duration => baseDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + placementInfo = SetupSupplyDrop.GetPlacementInfo(GetAimRay(), base.gameObject); + if (placementInfo.ok) + { + base.activatorSkillSlot.DeductStock(1); + } + } + if (placementInfo.ok) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, muzzleString, transmit: false); + base.characterBody.SetAimTimer(3f); + PlayAnimation("Gesture, Additive", CallSupplyDropStateHash, CallSupplyDropParamHash, duration); + PlayAnimation("Gesture, Override", CallSupplyDropStateHash, CallSupplyDropParamHash, duration); + if (NetworkServer.active) + { + GameObject obj = Object.Instantiate(supplyDropPrefab, placementInfo.position, placementInfo.rotation); + obj.GetComponent().teamIndex = base.teamComponent.teamIndex; + obj.GetComponent().ownerObject = base.gameObject; + Deployable component = obj.GetComponent(); + if ((bool)component && (bool)base.characterBody.master) + { + base.characterBody.master.AddDeployable(component, DeployableSlot.CaptainSupplyDrop); + } + ProjectileDamage component2 = obj.GetComponent(); + component2.crit = RollCrit(); + component2.damage = damageStat * impactDamageCoefficient; + component2.damageColorIndex = DamageColorIndex.Default; + component2.force = impactDamageForce; + component2.damageType = DamageType.Generic; + NetworkServer.Spawn(obj); + } + } + else + { + PlayCrossfade("Gesture, Additive", BufferEmptyStateHash, 0.1f); + PlayCrossfade("Gesture, Additive", BufferEmptyStateHash, 0.1f); + } + EntityStateMachine entityStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Skillswap"); + if ((bool)entityStateMachine) + { + entityStateMachine.SetNextStateToMain(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + placementInfo.Serialize(writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + placementInfo.Deserialize(reader); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropEquipmentRestock.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropEquipmentRestock.cs new file mode 100644 index 0000000..aaca83a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropEquipmentRestock.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropEquipmentRestock : CallSupplyDropBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropForce.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropForce.cs new file mode 100644 index 0000000..33ca685 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropForce.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropForce : CallSupplyDropBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropHacking.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropHacking.cs new file mode 100644 index 0000000..c8ed9c8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropHacking.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropHacking : CallSupplyDropBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropHealing.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropHealing.cs new file mode 100644 index 0000000..6bdccc3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropHealing.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropHealing : CallSupplyDropBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropPlating.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropPlating.cs new file mode 100644 index 0000000..096418a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropPlating.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropPlating : CallSupplyDropBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropShocking.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropShocking.cs new file mode 100644 index 0000000..87f3bc6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/CallSupplyDropShocking.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Captain.Weapon; + +public class CallSupplyDropShocking : CallSupplyDropBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/ChargeCaptainShotgun.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/ChargeCaptainShotgun.cs new file mode 100644 index 0000000..931fee7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/ChargeCaptainShotgun.cs @@ -0,0 +1,112 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class ChargeCaptainShotgun : BaseState +{ + public static float baseMinChargeDuration; + + public static float baseChargeDuration; + + public static string muzzleName; + + public static GameObject chargeupVfxPrefab; + + public static GameObject holdChargeVfxPrefab; + + public static string enterSoundString; + + public static string playChargeSoundString; + + public static string stopChargeSoundString; + + private float minChargeDuration; + + private float chargeDuration; + + private bool released; + + private GameObject chargeupVfxGameObject; + + private GameObject holdChargeVfxGameObject; + + private Transform muzzleTransform; + + private uint enterSoundID; + + public override void OnEnter() + { + base.OnEnter(); + minChargeDuration = baseMinChargeDuration / attackSpeedStat; + chargeDuration = baseChargeDuration / attackSpeedStat; + PlayCrossfade("Gesture, Override", "ChargeCaptainShotgun", "ChargeCaptainShotgun.playbackRate", chargeDuration, 0.1f); + PlayCrossfade("Gesture, Additive", "ChargeCaptainShotgun", "ChargeCaptainShotgun.playbackRate", chargeDuration, 0.1f); + muzzleTransform = FindModelChild(muzzleName); + if ((bool)muzzleTransform) + { + chargeupVfxGameObject = Object.Instantiate(chargeupVfxPrefab, muzzleTransform); + chargeupVfxGameObject.GetComponent().newDuration = chargeDuration; + } + enterSoundID = Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + Util.PlaySound(playChargeSoundString, base.gameObject); + } + + public override void OnExit() + { + if ((bool)chargeupVfxGameObject) + { + EntityState.Destroy(chargeupVfxGameObject); + chargeupVfxGameObject = null; + } + if ((bool)holdChargeVfxGameObject) + { + EntityState.Destroy(holdChargeVfxGameObject); + holdChargeVfxGameObject = null; + } + AkSoundEngine.StopPlayingID(enterSoundID); + Util.PlaySound(stopChargeSoundString, base.gameObject); + base.OnExit(); + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(base.age / chargeDuration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(1f); + Mathf.Clamp01(base.fixedAge / chargeDuration); + if (base.fixedAge >= chargeDuration) + { + if ((bool)chargeupVfxGameObject) + { + EntityState.Destroy(chargeupVfxGameObject); + chargeupVfxGameObject = null; + } + if (!holdChargeVfxGameObject && (bool)muzzleTransform) + { + holdChargeVfxGameObject = Object.Instantiate(holdChargeVfxPrefab, muzzleTransform); + } + } + if (base.isAuthority) + { + if (!released && (!base.inputBank || !base.inputBank.skill1.down)) + { + released = true; + } + if (released) + { + outer.SetNextState(new FireCaptainShotgun()); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/FireCaptainShotgun.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/FireCaptainShotgun.cs new file mode 100644 index 0000000..e51914a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/FireCaptainShotgun.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class FireCaptainShotgun : GenericBulletBaseState +{ + public static float tightSoundSwitchThreshold; + + public static string wideSoundString; + + public static string tightSoundString; + + private static int FireCaptainShotgunStateHash = Animator.StringToHash("FireCaptainShotgun"); + + public override void OnEnter() + { + fireSoundString = ((base.characterBody.spreadBloomAngle <= tightSoundSwitchThreshold) ? tightSoundString : wideSoundString); + base.OnEnter(); + PlayAnimation("Gesture, Additive", FireCaptainShotgunStateHash); + PlayAnimation("Gesture, Override", FireCaptainShotgunStateHash); + } + + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.falloffModel = BulletAttack.FalloffModel.DefaultBullet; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/FireTazer.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/FireTazer.cs new file mode 100644 index 0000000..dd7c855 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/FireTazer.cs @@ -0,0 +1,115 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class FireTazer : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject muzzleflashEffectPrefab; + + public static GameObject chargeEffectPrefab; + + public static float baseDelay = 0.1f; + + public static float baseDuration = 2f; + + public static float baseDurationUntilPriorityLowers = 1f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string enterSoundString; + + public static string attackString; + + public static float recoilAmplitude; + + public static float bloom; + + public static string targetMuzzle; + + private float duration; + + private float delay; + + private float durationUntilPriorityLowers; + + private static int FireTazerStateHash = Animator.StringToHash("FireTazer"); + + private static int FireTazerParamHash = Animator.StringToHash("FireTazer.playbackRate"); + + private bool hasFired; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + durationUntilPriorityLowers = baseDurationUntilPriorityLowers / attackSpeedStat; + delay = baseDelay / attackSpeedStat; + StartAimMode(duration + 2f); + if ((bool)chargeEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(chargeEffectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + PlayAnimation("Gesture, Additive", FireTazerStateHash, FireTazerParamHash, duration); + PlayAnimation("Gesture, Override", FireTazerStateHash, FireTazerParamHash, duration); + } + + private void Fire() + { + hasFired = true; + Util.PlaySound(attackString, base.gameObject); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + Ray ray = GetAimRay(); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= delay && !hasFired) + { + Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge > durationUntilPriorityLowers)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupAirstrike.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupAirstrike.cs new file mode 100644 index 0000000..4af55a5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupAirstrike.cs @@ -0,0 +1,108 @@ +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class SetupAirstrike : BaseState +{ + public static SkillDef primarySkillDef; + + public static GameObject crosshairOverridePrefab; + + public static string enterSoundString; + + public static string exitSoundString; + + public static GameObject effectMuzzlePrefab; + + public static string effectMuzzleString; + + public static float baseExitDuration; + + private GenericSkill primarySkillSlot; + + private GameObject effectMuzzleInstance; + + private Animator modelAnimator; + + private float timerSinceComplete; + + private bool beginExit; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private static int PrepAirstrikeHash = Animator.StringToHash("PrepAirstrike"); + + private float exitDuration => baseExitDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + primarySkillSlot = (base.skillLocator ? base.skillLocator.primary : null); + if ((bool)primarySkillSlot) + { + primarySkillSlot.SetSkillOverride(this, primarySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(PrepAirstrikeHash, value: true); + } + PlayCrossfade("Gesture, Override", PrepAirstrikeHash, 0.1f); + PlayCrossfade("Gesture, Additive", PrepAirstrikeHash, 0.1f); + Transform transform = FindModelChild(effectMuzzleString); + if ((bool)transform) + { + effectMuzzleInstance = Object.Instantiate(effectMuzzlePrefab, transform); + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Util.PlaySound(enterSoundString, base.gameObject); + Util.PlaySound("Play_captain_shift_active_loop", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if (!primarySkillSlot || primarySkillSlot.stock == 0) + { + beginExit = true; + } + if (beginExit) + { + timerSinceComplete += GetDeltaTime(); + if (timerSinceComplete > exitDuration) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + if ((bool)primarySkillSlot) + { + primarySkillSlot.UnsetSkillOverride(this, primarySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + Util.PlaySound(exitSoundString, base.gameObject); + Util.PlaySound("Stop_captain_shift_active_loop", base.gameObject); + if ((bool)effectMuzzleInstance) + { + EntityState.Destroy(effectMuzzleInstance); + } + if ((bool)modelAnimator) + { + modelAnimator.SetBool(PrepAirstrikeHash, value: false); + } + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupAirstrikeAlt.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupAirstrikeAlt.cs new file mode 100644 index 0000000..9550533 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupAirstrikeAlt.cs @@ -0,0 +1,108 @@ +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Captain.Weapon; + +public class SetupAirstrikeAlt : BaseState +{ + public static SkillDef primarySkillDef; + + public static GameObject crosshairOverridePrefab; + + public static string enterSoundString; + + public static string exitSoundString; + + public static GameObject effectMuzzlePrefab; + + public static string effectMuzzleString; + + public static float baseExitDuration; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private GenericSkill primarySkillSlot; + + private GameObject effectMuzzleInstance; + + private Animator modelAnimator; + + private float timerSinceComplete; + + private bool beginExit; + + private static int PrepAirstrikeHash = Animator.StringToHash("PrepAirstrike"); + + private float exitDuration => baseExitDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + primarySkillSlot = (base.skillLocator ? base.skillLocator.primary : null); + if ((bool)primarySkillSlot) + { + primarySkillSlot.SetSkillOverride(this, primarySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(PrepAirstrikeHash, value: true); + } + PlayCrossfade("Gesture, Override", PrepAirstrikeHash, 0.1f); + PlayCrossfade("Gesture, Additive", PrepAirstrikeHash, 0.1f); + Transform transform = FindModelChild(effectMuzzleString); + if ((bool)transform) + { + effectMuzzleInstance = Object.Instantiate(effectMuzzlePrefab, transform); + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Util.PlaySound(enterSoundString, base.gameObject); + Util.PlaySound("Play_captain_shift_active_loop", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if (!primarySkillSlot || primarySkillSlot.stock == 0) + { + beginExit = true; + } + if (beginExit) + { + timerSinceComplete += GetDeltaTime(); + if (timerSinceComplete > exitDuration) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + if ((bool)primarySkillSlot) + { + primarySkillSlot.UnsetSkillOverride(this, primarySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + Util.PlaySound(exitSoundString, base.gameObject); + Util.PlaySound("Stop_captain_shift_active_loop", base.gameObject); + if ((bool)effectMuzzleInstance) + { + EntityState.Destroy(effectMuzzleInstance); + } + if ((bool)modelAnimator) + { + modelAnimator.SetBool(PrepAirstrikeHash, value: false); + } + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupSupplyDrop.cs b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupSupplyDrop.cs new file mode 100644 index 0000000..dd6f000 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Captain.Weapon/SetupSupplyDrop.cs @@ -0,0 +1,187 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Captain.Weapon; + +public class SetupSupplyDrop : BaseState +{ + public struct PlacementInfo + { + public bool ok; + + public Vector3 position; + + public Quaternion rotation; + + public void Serialize(NetworkWriter writer) + { + writer.Write(ok); + writer.Write(position); + writer.Write(rotation); + } + + public void Deserialize(NetworkReader reader) + { + ok = reader.ReadBoolean(); + position = reader.ReadVector3(); + rotation = reader.ReadQuaternion(); + } + } + + public static GameObject crosshairOverridePrefab; + + public static string enterSoundString; + + public static string exitSoundString; + + public static GameObject effectMuzzlePrefab; + + public static string effectMuzzleString; + + public static float baseExitDuration; + + public static float maxPlacementDistance; + + public static GameObject blueprintPrefab; + + public static float normalYThreshold; + + private PlacementInfo currentPlacementInfo; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private GenericSkill primarySkillSlot; + + private AimAnimator modelAimAnimator; + + private GameObject effectMuzzleInstance; + + private Animator modelAnimator; + + private float timerSinceComplete; + + private bool beginExit; + + private GenericSkill originalPrimarySkill; + + private GenericSkill originalSecondarySkill; + + private BlueprintController blueprints; + + private CameraTargetParams.AimRequest aimRequest; + + private static int PrepSupplyDropStateHash = Animator.StringToHash("PrepSupplyDrop"); + + private float exitDuration => baseExitDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + PlayAnimation("Gesture, Override", PrepSupplyDropStateHash); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(PrepSupplyDropStateHash, value: true); + } + Transform transform = FindModelChild(effectMuzzleString); + if ((bool)transform) + { + effectMuzzleInstance = Object.Instantiate(effectMuzzlePrefab, transform); + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Util.PlaySound(enterSoundString, base.gameObject); + blueprints = Object.Instantiate(blueprintPrefab, currentPlacementInfo.position, currentPlacementInfo.rotation).GetComponent(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + originalPrimarySkill = base.skillLocator.primary; + originalSecondarySkill = base.skillLocator.secondary; + base.skillLocator.primary = base.skillLocator.FindSkill("SupplyDrop1"); + base.skillLocator.secondary = base.skillLocator.FindSkill("SupplyDrop2"); + } + + public override void Update() + { + base.Update(); + currentPlacementInfo = GetPlacementInfo(GetAimRay(), base.gameObject); + if ((bool)blueprints) + { + blueprints.PushState(currentPlacementInfo.position, currentPlacementInfo.rotation, currentPlacementInfo.ok); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if (base.isAuthority && beginExit) + { + timerSinceComplete += GetDeltaTime(); + if (timerSinceComplete > exitDuration) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + Util.PlaySound(exitSoundString, base.gameObject); + } + if ((bool)effectMuzzleInstance) + { + EntityState.Destroy(effectMuzzleInstance); + } + crosshairOverrideRequest?.Dispose(); + base.skillLocator.primary = originalPrimarySkill; + base.skillLocator.secondary = originalSecondarySkill; + if ((bool)modelAnimator) + { + modelAnimator.SetBool(PrepSupplyDropStateHash, value: false); + } + if ((bool)blueprints) + { + EntityState.Destroy(blueprints.gameObject); + blueprints = null; + } + aimRequest?.Dispose(); + base.OnExit(); + } + + public static PlacementInfo GetPlacementInfo(Ray aimRay, GameObject gameObject) + { + float extraRaycastDistance = 0f; + CameraRigController.ModifyAimRayIfApplicable(aimRay, gameObject, out extraRaycastDistance); + Vector3 vector = -aimRay.direction; + Vector3 vector2 = Vector3.up; + Vector3 lhs = Vector3.Cross(vector2, vector); + PlacementInfo result = default(PlacementInfo); + result.ok = false; + if (Physics.Raycast(aimRay, out var hitInfo, maxPlacementDistance, LayerIndex.world.mask) && hitInfo.normal.y > normalYThreshold) + { + vector2 = hitInfo.normal; + vector = Vector3.Cross(lhs, vector2); + result.ok = true; + } + result.rotation = Util.QuaternionSafeLookRotation(vector, vector2); + Vector3 point = hitInfo.point; + result.position = point; + return result; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainDefenseMatrixItem/DefenseMatrixOn.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainDefenseMatrixItem/DefenseMatrixOn.cs new file mode 100644 index 0000000..4ad1919 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainDefenseMatrixItem/DefenseMatrixOn.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.CaptainDefenseMatrixItem; + +public class DefenseMatrixOn : BaseBodyAttachmentState +{ + public static float projectileEraserRadius; + + public static float minimumFireFrequency; + + public static float baseRechargeFrequency; + + public static GameObject tracerEffectPrefab; + + private float rechargeTimer; + + private float rechargeFrequency => baseRechargeFrequency * (base.attachedBody ? base.attachedBody.attackSpeed : 1f); + + private float fireFrequency => Mathf.Max(minimumFireFrequency, rechargeFrequency); + + private float timeBetweenFiring => 1f / fireFrequency; + + private bool isReadyToFire => rechargeTimer <= 0f; + + protected int GetItemStack() + { + if (!base.attachedBody || !base.attachedBody.inventory) + { + return 1; + } + return base.attachedBody.inventory.GetItemCount(RoR2Content.Items.CaptainDefenseMatrix); + } + + public override void OnEnter() + { + base.OnEnter(); + if (!base.attachedBody) + { + return; + } + PlayerCharacterMasterController component = base.attachedBody.master.GetComponent(); + if ((bool)component) + { + NetworkUser networkUser = component.networkUser; + if ((bool)networkUser) + { + PickupIndex pickupIndex = PickupCatalog.FindPickupIndex(RoR2Content.Items.CaptainDefenseMatrix.itemIndex); + networkUser.localUser?.userProfile.DiscoverPickup(pickupIndex); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!NetworkServer.active) + { + return; + } + rechargeTimer -= GetDeltaTime(); + if (base.fixedAge > timeBetweenFiring) + { + base.fixedAge -= timeBetweenFiring; + if (isReadyToFire && DeleteNearbyProjectile()) + { + rechargeTimer = 1f / rechargeFrequency; + } + } + } + + private bool DeleteNearbyProjectile() + { + Vector3 vector = (base.attachedBody ? base.attachedBody.corePosition : Vector3.zero); + TeamIndex teamIndex = (base.attachedBody ? base.attachedBody.teamComponent.teamIndex : TeamIndex.None); + float num = projectileEraserRadius * projectileEraserRadius; + int num2 = 0; + int itemStack = GetItemStack(); + bool result = false; + List instancesList = InstanceTracker.GetInstancesList(); + List list = new List(); + int i = 0; + for (int count = instancesList.Count; i < count; i++) + { + if (num2 >= itemStack) + { + break; + } + ProjectileController projectileController = instancesList[i]; + if (!projectileController.cannotBeDeleted && projectileController.teamFilter.teamIndex != teamIndex && (projectileController.transform.position - vector).sqrMagnitude < num) + { + list.Add(projectileController); + num2++; + } + } + int j = 0; + for (int count2 = list.Count; j < count2; j++) + { + ProjectileController projectileController2 = list[j]; + if ((bool)projectileController2) + { + result = true; + Vector3 position = projectileController2.transform.position; + Vector3 start = vector; + if ((bool)tracerEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = position, + start = start + }; + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + } + EntityState.Destroy(projectileController2.gameObject); + } + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/BaseCaptainSupplyDropState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/BaseCaptainSupplyDropState.cs new file mode 100644 index 0000000..2645750 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/BaseCaptainSupplyDropState.cs @@ -0,0 +1,109 @@ +using RoR2; +using UnityEngine; +using UnityEngine.UI; + +namespace EntityStates.CaptainSupplyDrop; + +public class BaseCaptainSupplyDropState : BaseState +{ + private ProxyInteraction interactionComponent; + + protected GenericEnergyComponent energyComponent; + + protected TeamFilter teamFilter; + + private Image energyIndicator; + + private GameObject energyIndicatorContainer; + + protected virtual bool shouldShowModel => true; + + protected virtual bool shouldShowEnergy => false; + + protected virtual string GetContextString(Interactor activator) + { + return null; + } + + protected virtual Interactability GetInteractability(Interactor activator) + { + return Interactability.Disabled; + } + + protected virtual void OnInteractionBegin(Interactor activator) + { + } + + protected virtual bool ShouldShowOnScanner() + { + return false; + } + + protected virtual bool ShouldIgnoreSpherecastForInteractability(Interactor activator) + { + return false; + } + + private string GetContextStringInternal(ProxyInteraction proxyInteraction, Interactor activator) + { + return GetContextString(activator); + } + + private Interactability GetInteractabilityInternal(ProxyInteraction proxyInteraction, Interactor activator) + { + return GetInteractability(activator); + } + + private void OnInteractionBeginInternal(ProxyInteraction proxyInteraction, Interactor activator) + { + OnInteractionBegin(activator); + } + + private bool ShouldIgnoreSpherecastForInteractabilityInternal(ProxyInteraction proxyInteraction, Interactor activator) + { + return ShouldIgnoreSpherecastForInteractability(activator); + } + + private bool ShouldShowOnScannerInternal(ProxyInteraction proxyInteraction) + { + return ShouldShowOnScanner(); + } + + public override void OnEnter() + { + base.OnEnter(); + energyComponent = GetComponent(); + teamFilter = GetComponent(); + interactionComponent = GetComponent(); + interactionComponent.getContextString = GetContextStringInternal; + interactionComponent.getInteractability = GetInteractabilityInternal; + interactionComponent.onInteractionBegin = OnInteractionBeginInternal; + interactionComponent.shouldShowOnScanner = ShouldShowOnScannerInternal; + interactionComponent.shouldIgnoreSpherecastForInteractability = ShouldIgnoreSpherecastForInteractabilityInternal; + GetModelTransform().gameObject.SetActive(shouldShowModel); + energyIndicatorContainer = FindModelChild("EnergyIndicatorContainer").gameObject; + energyIndicator = FindModelChild("EnergyIndicator").GetComponent(); + } + + public override void OnExit() + { + interactionComponent.getContextString = null; + interactionComponent.getInteractability = null; + interactionComponent.onInteractionBegin = null; + interactionComponent.shouldShowOnScanner = null; + interactionComponent.shouldIgnoreSpherecastForInteractability = null; + base.OnExit(); + } + + public override void Update() + { + base.Update(); + UpdateEnergyIndicator(); + } + + private void UpdateEnergyIndicator() + { + energyIndicatorContainer.SetActive(shouldShowEnergy); + energyIndicator.fillAmount = energyComponent.normalizedEnergy; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/BaseMainState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/BaseMainState.cs new file mode 100644 index 0000000..5ef3af7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/BaseMainState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.CaptainSupplyDrop; + +public abstract class BaseMainState : BaseCaptainSupplyDropState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/DepletionState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/DepletionState.cs new file mode 100644 index 0000000..f0782b3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/DepletionState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.CaptainSupplyDrop; + +public class DepletionState : BaseCaptainSupplyDropState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/DeployState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/DeployState.cs new file mode 100644 index 0000000..c5ab12e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/DeployState.cs @@ -0,0 +1,23 @@ +namespace EntityStates.CaptainSupplyDrop; + +public class DeployState : BaseCaptainSupplyDropState +{ + public static float baseDuration; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/EntryState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/EntryState.cs new file mode 100644 index 0000000..72e91e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/EntryState.cs @@ -0,0 +1,25 @@ +namespace EntityStates.CaptainSupplyDrop; + +public class EntryState : BaseCaptainSupplyDropState +{ + public static float baseDuration; + + private float duration; + + protected override bool shouldShowModel => false; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new HitGroundState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/EquipmentRestockMainState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/EquipmentRestockMainState.cs new file mode 100644 index 0000000..6474c52 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/EquipmentRestockMainState.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.CaptainSupplyDrop; + +public class EquipmentRestockMainState : BaseMainState +{ + [SerializeField] + public float activationCost; + + protected override bool shouldShowEnergy => true; + + protected override string GetContextString(Interactor activator) + { + return Language.GetString("CAPTAIN_SUPPLY_EQUIPMENT_RESTOCK_INTERACTION"); + } + + protected override Interactability GetInteractability(Interactor activator) + { + CharacterBody component = activator.GetComponent(); + Inventory inventory; + if (!component || !(inventory = component.inventory)) + { + return Interactability.Disabled; + } + if (activationCost >= energyComponent.energy) + { + return Interactability.ConditionsNotMet; + } + if (inventory.GetEquipmentRestockableChargeCount(inventory.activeEquipmentSlot) <= 0) + { + return Interactability.ConditionsNotMet; + } + return Interactability.Available; + } + + protected override void OnInteractionBegin(Interactor activator) + { + energyComponent.TakeEnergy(activationCost); + Inventory inventory = activator.GetComponent().inventory; + inventory.RestockEquipmentCharges(inventory.activeEquipmentSlot, 1); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HackingInProgressState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HackingInProgressState.cs new file mode 100644 index 0000000..5caadab --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HackingInProgressState.cs @@ -0,0 +1,101 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.CaptainSupplyDrop; + +public class HackingInProgressState : BaseMainState +{ + public static int baseGoldForBaseDuration = 25; + + public static float baseDuration = 15f; + + public static GameObject targetIndicatorVfxPrefab; + + public PurchaseInteraction target; + + private GameObject targetIndicatorVfxInstance; + + private Run.FixedTimeStamp startTime; + + private Run.FixedTimeStamp endTime; + + protected override bool shouldShowEnergy => true; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + int difficultyScaledCost = Run.instance.GetDifficultyScaledCost(baseGoldForBaseDuration, Stage.instance.entryDifficultyCoefficient); + float num = (float)((double)target.cost / (double)difficultyScaledCost * (double)baseDuration); + startTime = Run.FixedTimeStamp.now; + endTime = startTime + num; + } + energyComponent.normalizedChargeRate = 1f / (endTime - startTime); + if (NetworkServer.active) + { + energyComponent.energy = 0f; + } + if (!targetIndicatorVfxPrefab || !target) + { + return; + } + targetIndicatorVfxInstance = Object.Instantiate(targetIndicatorVfxPrefab, target.transform.position, Quaternion.identity); + ChildLocator component = targetIndicatorVfxInstance.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("LineEnd"); + if ((bool)transform) + { + transform.position = FindModelChild("ShaftTip").position; + } + } + } + + public override void OnExit() + { + if ((bool)targetIndicatorVfxInstance) + { + EntityState.Destroy(targetIndicatorVfxInstance); + targetIndicatorVfxInstance = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (energyComponent.normalizedEnergy >= 1f) + { + outer.SetNextState(new UnlockTargetState + { + target = target + }); + } + else if (!HackingMainState.PurchaseInteractionIsValidTarget(target)) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(target ? target.gameObject : null); + writer.Write(startTime); + writer.Write(endTime); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + GameObject gameObject = reader.ReadGameObject(); + target = (gameObject ? gameObject.GetComponent() : null); + startTime = reader.ReadFixedTimeStamp(); + endTime = reader.ReadFixedTimeStamp(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HackingMainState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HackingMainState.cs new file mode 100644 index 0000000..ec9bc82 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HackingMainState.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using HG; +using RoR2; +using UnityEngine; + +namespace EntityStates.CaptainSupplyDrop; + +public class HackingMainState : BaseMainState +{ + public static float baseRadius = 7f; + + public static float scanInterval = 5f; + + private float radius; + + private float scanTimer; + + private SphereSearch sphereSearch; + + public override void OnEnter() + { + base.OnEnter(); + radius = baseRadius; + if (base.isAuthority) + { + sphereSearch = new SphereSearch(); + sphereSearch.origin = base.transform.position; + sphereSearch.mask = LayerIndex.CommonMasks.interactable; + sphereSearch.queryTriggerInteraction = QueryTriggerInteraction.Collide; + sphereSearch.radius = radius; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private PurchaseInteraction ScanForTarget() + { + List list = CollectionPool>.RentCollection(); + sphereSearch.ClearCandidates(); + sphereSearch.RefreshCandidates(); + sphereSearch.FilterCandidatesByColliderEntities(); + sphereSearch.OrderCandidatesByDistance(); + sphereSearch.FilterCandidatesByDistinctColliderEntities(); + sphereSearch.GetColliders(list); + PurchaseInteraction result = null; + int i = 0; + for (int count = list.Count; i < count; i++) + { + PurchaseInteraction component = list[i].GetComponent().entity.GetComponent(); + if (PurchaseInteractionIsValidTarget(component)) + { + result = component; + break; + } + } + CollectionPool>.ReturnCollection(list); + return result; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + scanTimer -= GetDeltaTime(); + if (scanTimer <= 0f) + { + scanTimer = scanInterval; + PurchaseInteraction purchaseInteraction = ScanForTarget(); + if ((bool)purchaseInteraction) + { + outer.SetNextState(new HackingInProgressState + { + target = purchaseInteraction + }); + } + } + } + + public static bool PurchaseInteractionIsValidTarget(PurchaseInteraction purchaseInteraction) + { + if ((bool)purchaseInteraction) + { + if (purchaseInteraction.costType == CostTypeIndex.Money && purchaseInteraction.cost > 0) + { + return purchaseInteraction.available; + } + return false; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HealZoneMainState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HealZoneMainState.cs new file mode 100644 index 0000000..c9a1770 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HealZoneMainState.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.CaptainSupplyDrop; + +public class HealZoneMainState : BaseMainState +{ + public static GameObject healZonePrefab; + + private GameObject healZoneInstance; + + protected override Interactability GetInteractability(Interactor activator) + { + return Interactability.Disabled; + } + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + healZoneInstance = Object.Instantiate(healZonePrefab, base.transform.position, base.transform.rotation); + healZoneInstance.GetComponent().teamIndex = teamFilter.teamIndex; + NetworkServer.Spawn(healZoneInstance); + } + } + + public override void OnExit() + { + if ((bool)healZoneInstance) + { + EntityState.Destroy(healZoneInstance); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HitGroundState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HitGroundState.cs new file mode 100644 index 0000000..cd5ca3f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/HitGroundState.cs @@ -0,0 +1,64 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.CaptainSupplyDrop; + +public class HitGroundState : BaseCaptainSupplyDropState +{ + public static float baseDuration; + + public static GameObject effectPrefab; + + public static float impactBulletDistance; + + public static float impactBulletRadius; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + if (NetworkServer.active) + { + GameObject ownerObject = GetComponent().ownerObject; + ProjectileDamage component = GetComponent(); + Vector3 position = base.transform.position; + Vector3 vector = -base.transform.up; + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.origin = position - vector * impactBulletDistance; + bulletAttack.aimVector = vector; + bulletAttack.maxDistance = impactBulletDistance + 1f; + bulletAttack.stopperMask = default(LayerMask); + bulletAttack.hitMask = LayerIndex.CommonMasks.bullet; + bulletAttack.damage = component.damage; + bulletAttack.damageColorIndex = component.damageColorIndex; + bulletAttack.damageType = component.damageType; + bulletAttack.bulletCount = 1u; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = 0f; + bulletAttack.owner = ownerObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.procCoefficient = 0f; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.isCrit = RollCrit(); + bulletAttack.smartCollision = false; + bulletAttack.sniper = false; + bulletAttack.force = component.force; + bulletAttack.radius = impactBulletRadius; + bulletAttack.hitEffectPrefab = effectPrefab; + bulletAttack.Fire(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new DeployState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/PlatingBuffMainState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/PlatingBuffMainState.cs new file mode 100644 index 0000000..9b732c3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/PlatingBuffMainState.cs @@ -0,0 +1,58 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.CaptainSupplyDrop; + +public class PlatingBuffMainState : BaseMainState +{ + public static int maximumBuffStack; + + public static int buffCountToGrant; + + [SerializeField] + public float activationCost; + + private static BuffIndex buff => JunkContent.Buffs.BodyArmor.buffIndex; + + protected override bool shouldShowEnergy => true; + + protected override string GetContextString(Interactor activator) + { + return Language.GetString("CAPTAIN_SUPPLY_DEFENSE_RESTOCK_INTERACTION"); + } + + protected override Interactability GetInteractability(Interactor activator) + { + CharacterBody component = activator.GetComponent(); + if (!component) + { + return Interactability.Disabled; + } + if (energyComponent.energy < activationCost) + { + return Interactability.ConditionsNotMet; + } + if (component.GetBuffCount(buff) >= maximumBuffStack) + { + return Interactability.ConditionsNotMet; + } + return Interactability.Available; + } + + protected override void OnInteractionBegin(Interactor activator) + { + CharacterBody component = activator.GetComponent(); + for (int i = 0; i < buffCountToGrant; i++) + { + if (component.GetBuffCount(buff) >= maximumBuffStack) + { + break; + } + if (!energyComponent.TakeEnergy(activationCost)) + { + break; + } + component.AddBuff(buff); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/PreDepletionState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/PreDepletionState.cs new file mode 100644 index 0000000..90093ae --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/PreDepletionState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.CaptainSupplyDrop; + +public class PreDepletionState : BaseCaptainSupplyDropState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/ShockZoneMainState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/ShockZoneMainState.cs new file mode 100644 index 0000000..a8cd33b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/ShockZoneMainState.cs @@ -0,0 +1,64 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.CaptainSupplyDrop; + +public class ShockZoneMainState : BaseMainState +{ + public static GameObject shockEffectPrefab; + + public static float shockRadius; + + public static float shockDamageCoefficient; + + public static float shockFrequency; + + private float shockTimer; + + protected override Interactability GetInteractability(Interactor activator) + { + return Interactability.Disabled; + } + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + shockTimer += GetDeltaTime(); + if (shockTimer > 1f / shockFrequency) + { + shockTimer -= 1f / shockFrequency; + Shock(); + } + } + + private void Shock() + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.radius = shockRadius; + blastAttack.baseDamage = 0f; + blastAttack.damageType = DamageType.Silent | DamageType.Shock5s; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.attacker = null; + blastAttack.teamIndex = teamFilter.teamIndex; + blastAttack.position = base.transform.position; + blastAttack.Fire(); + if ((bool)shockEffectPrefab) + { + EffectManager.SpawnEffect(shockEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = shockRadius + }, transmit: false); + } + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/UnlockTargetState.cs b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/UnlockTargetState.cs new file mode 100644 index 0000000..3384e82 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.CaptainSupplyDrop/UnlockTargetState.cs @@ -0,0 +1,64 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.CaptainSupplyDrop; + +public class UnlockTargetState : BaseMainState +{ + public static GameObject unlockEffectPrefab; + + public static float baseDuration; + + public static string soundString; + + public PurchaseInteraction target; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active && (bool)target && target.available) + { + target.Networkcost = 0; + GameObject ownerObject = GetComponent().ownerObject; + if ((bool)ownerObject) + { + Interactor component = ownerObject.GetComponent(); + if ((bool)component) + { + component.AttemptInteraction(target.gameObject); + } + } + EffectManager.SpawnEffect(unlockEffectPrefab, new EffectData + { + origin = target.transform.position + }, transmit: true); + } + Util.PlaySound(soundString, base.gameObject); + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(target ? target.gameObject : null); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + GameObject gameObject = reader.ReadGameObject(); + target = (gameObject ? gameObject.GetComponent() : null); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/ChargeRolyPoly.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/ChargeRolyPoly.cs new file mode 100644 index 0000000..5dab665 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/ChargeRolyPoly.cs @@ -0,0 +1,315 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Chef; + +public class ChargeRolyPoly : BaseSkillState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float baseChargeDuration = 1f; + + [SerializeField] + public float minChargeForChargedAttack = 0.1f; + + [SerializeField] + public float walkSpeedCoefficient; + + [SerializeField] + public GameObject skiddingVFX1; + + [SerializeField] + public string chargeLevelSFX1; + + [SerializeField] + public string chargeLevelSFX2; + + [SerializeField] + public string chargeLevelSFX3; + + [SerializeField] + public float explosionDmgCoefficient; + + [SerializeField] + public float dmgIncreasePercent; + + [SerializeField] + public float explosionForce; + + [SerializeField] + public Vector3 extraExplosionForce; + + [SerializeField] + public float explosionRadius; + + [SerializeField] + public GameObject explosionPrefab1; + + [SerializeField] + public GameObject explosionPrefab2; + + [SerializeField] + public GameObject explosionPrefab3; + + [SerializeField] + public float explodeRadiusVFX; + + private float duration; + + private GameObject explosionPrefab; + + private int gearShifLevel; + + private GameObject chargeLevelVFXBase; + + private bool chargeAnimPlayed; + + private float gearToChargeProgress = 0.3f; + + private bool obtainedGear1; + + private bool obtainedGear2; + + private bool obtainedGear3; + + private Transform modelTransform; + + private EffectManagerHelper rolyPolyChargeFXReference; + + private bool hasBoost; + + private bool useRootMotion; + + private bool hasCharacterMotor; + + private bool hasRailMotor; + + private bool hasCharacterDirection; + + private bool hasAimAnimator; + + private AimAnimator aimAnimator; + + private Vector3 moveVector = Vector3.zero; + + private Vector3 aimDirection = Vector3.forward; + + private ChefController chefController; + + protected float charge { get; private set; } + + protected float chargeDuration { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + chefController = base.characterBody.GetComponent(); + if (chefController != null) + { + chefController.blockOtherSkills = true; + } + EntityStateMachine.FindByCustomName(base.gameObject, "Weapon").SetNextState(new RolyPolyWeaponBlockingState()); + } + bool active = NetworkServer.active; + chargeDuration = baseChargeDuration / attackSpeedStat; + if (base.characterBody.HasBuff(DLC2Content.Buffs.Boosted)) + { + hasBoost = true; + if (active) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.Boosted); + } + } + if (active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.ArmorBoost); + } + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + PlayAnimation("Body", "ChargeRolyPoly", "ChargeRolyPoly.playbackRate", 1f); + new EffectData + { + origin = base.transform.position, + scale = 1f + }; + modelTransform = GetModelTransform(); + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform inTransform = component.FindChild("Base"); + rolyPolyChargeFXReference = EffectManager.GetAndActivatePooledEffect(skiddingVFX1, inTransform, inResetLocal: true); + } + useRootMotion = ((bool)base.characterBody && base.characterBody.rootMotionInMainState && base.isGrounded) || (bool)base.railMotor; + hasCharacterMotor = base.characterMotor; + hasRailMotor = base.railMotor; + hasCharacterDirection = base.characterDirection; + Util.PlaySound("Play_chef_skill3_charge_start", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeForChargedAttack && charge != 1f && charge >= gearToChargeProgress) + { + gearToChargeProgress += 0.3f; + explosionDmgCoefficient += explosionDmgCoefficient * dmgIncreasePercent; + GearShift(); + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + private void GearShift() + { + switch (gearShifLevel) + { + case 0: + explosionPrefab = explosionPrefab1; + Util.PlaySound(chargeLevelSFX1, base.gameObject); + break; + case 1: + explosionPrefab = explosionPrefab2; + Util.PlaySound(chargeLevelSFX2, base.gameObject); + break; + case 2: + explosionPrefab = explosionPrefab3; + Util.PlaySound(chargeLevelSFX3, base.gameObject); + break; + } + EffectManager.SpawnEffect(explosionPrefab, new EffectData + { + origin = base.characterBody.footPosition, + scale = explosionRadius * explodeRadiusVFX + }, transmit: true); + gearShifLevel++; + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.characterBody.gameObject; + blastAttack.baseDamage = explosionDmgCoefficient * base.characterBody.damage; + blastAttack.baseForce = explosionForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.crit = base.characterBody.RollCrit(); + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.damageType = DamageType.SlowOnHit; + blastAttack.inflictor = base.gameObject; + blastAttack.position = base.transform.position; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = 1f; + blastAttack.radius = explosionRadius; + blastAttack.teamIndex = base.characterBody.teamComponent.teamIndex; + blastAttack.bonusForce = extraExplosionForce; + blastAttack.Fire(); + } + + private void AuthorityFixedUpdate() + { + if (base.inputBank.skill3.justReleased || charge > 0.9f) + { + if (charge >= 0.9f) + { + charge = 3f; + } + else if (charge >= 0.6f) + { + charge = 2f; + } + else if (charge >= 0.3f) + { + charge = 1f; + } + else + { + charge = 0f; + } + outer.SetNextState(GetNextStateAuthority()); + } + else + { + HandleRotation(); + } + } + + private void HandleRotation() + { + moveVector = base.inputBank.moveVector; + aimDirection = base.inputBank.aimDirection; + if (useRootMotion) + { + if (hasCharacterMotor) + { + base.characterMotor.moveDirection = Vector3.zero; + } + if (hasRailMotor) + { + base.railMotor.inputMoveVector = moveVector; + } + } + else + { + if (hasCharacterMotor) + { + base.characterMotor.moveDirection = moveVector; + } + if (hasRailMotor) + { + base.railMotor.inputMoveVector = moveVector; + } + } + if (!hasRailMotor && hasCharacterDirection) + { + if (hasAimAnimator && aimAnimator.aimType == AimAnimator.AimType.Smart) + { + Vector3 vector = ((moveVector == Vector3.zero) ? base.characterDirection.forward : moveVector); + float num = Vector3.Angle(aimDirection, vector); + float num2 = Mathf.Max(aimAnimator.pitchRangeMax + aimAnimator.pitchGiveupRange, aimAnimator.yawRangeMax + aimAnimator.yawGiveupRange); + base.characterDirection.moveVector = (((bool)base.characterBody && base.characterBody.shouldAim && num > num2) ? aimDirection : vector); + } + else + { + base.characterDirection.moveVector = (((bool)base.characterBody && base.characterBody.shouldAim) ? aimDirection : moveVector); + } + } + } + + public override void OnExit() + { + if (rolyPolyChargeFXReference != null) + { + rolyPolyChargeFXReference.ReturnToPool(); + rolyPolyChargeFXReference = null; + } + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.ArmorBoost); + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + if (base.isAuthority && chefController != null) + { + chefController.blockOtherSkills = hasBoost; + } + Util.PlaySound("Stop_chef_skill3_charge_loop", base.gameObject); + base.OnExit(); + } + + protected virtual EntityState GetNextStateAuthority() + { + return new RolyPoly + { + charge = charge, + hasBoost = hasBoost + }; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/ChefsKiss.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/ChefsKiss.cs new file mode 100644 index 0000000..9c20e98 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/ChefsKiss.cs @@ -0,0 +1,8 @@ +namespace EntityStates.Chef; + +public class ChefsKiss : BaseState +{ + public override void OnEnter() + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/Dice.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/Dice.cs new file mode 100644 index 0000000..908135b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/Dice.cs @@ -0,0 +1,251 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Chef; + +public class Dice : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject projectileEnhancedPrefab; + + [SerializeField] + public GameObject effectEnhancedPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float boostedDamageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackString; + + [SerializeField] + public string returnString; + + [SerializeField] + public string yesChefAttackString; + + [SerializeField] + public string yesChefReturnString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public float recallAnimationTransitionTime = 0.2f; + + [SerializeField] + public float approximateCleaverDistance = 80f; + + private float duration; + + private ChefController chefController; + + private bool hasBoost; + + private bool recallInputPressed; + + private const float recallBackupCountdown_Duration = 3f; + + private float recallBackupCountdown = 3f; + + public override void OnEnter() + { + base.OnEnter(); + recallBackupCountdown = 3f; + if (!chefController) + { + chefController = GetComponent(); + } + chefController.characterBody = base.characterBody; + chefController.spreadBloom = bloom; + hasBoost = base.characterBody.HasBuff(DLC2Content.Buffs.Boosted); + if (hasBoost) + { + damageCoefficient = boostedDamageCoefficient; + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.Boosted); + } + } + chefController.NetworkcatchDirtied = false; + chefController.recallCleaver = false; + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, approximateCleaverDistance, base.gameObject); + duration = baseDuration; + StartAimMode(duration + 2f); + if (hasBoost) + { + PlayAnimation("Gesture, Override", "FireSliceAndDice", "FireSliceAndDice.playbackRate", duration); + PlayAnimation("Gesture, Additive", "FireSliceAndDice", "FireSliceAndDice.playbackRate", duration); + Util.PlaySound(yesChefAttackString, base.gameObject); + } + else + { + PlayAnimation("Gesture, Override", "FireDice", "FireDice.playbackRate", duration); + PlayAnimation("Gesture, Additive", "FireDice", "FireDice.playbackRate", duration); + Util.PlaySound(attackString, base.gameObject); + } + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + string muzzleName = "MouthMuzzle"; + GameObject gameObject = (hasBoost ? effectEnhancedPrefab : effectPrefab); + if ((bool)gameObject) + { + EffectManager.SimpleMuzzleFlash(gameObject, base.characterBody.aimOriginTransform.gameObject, muzzleName, transmit: false); + } + chefController.cleaverAway = true; + if (!base.isAuthority) + { + return; + } + GameObject gameObject2 = (hasBoost ? projectileEnhancedPrefab : projectilePrefab); + int[] array = ((!hasBoost) ? new int[1] { 1 } : new int[3] { 8, 4, 4 }); + int num = array.Length; + for (int i = 0; i < num; i++) + { + int num2 = array[i]; + float num3 = (float)(i % 2) * (0.5f / (float)num2); + for (int j = 0; j < num2; j++) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = gameObject2; + fireProjectileInfo.position = ray.origin; + float f = (num3 + (float)j / (float)num2) * MathF.PI * 2f; + float f2 = Mathf.Acos(0.02f + (float)i / (float)num); + float x = Mathf.Sin(f2) * Mathf.Sin(f); + float y = Mathf.Cos(f2); + float z = Mathf.Sin(f2) * Mathf.Cos(f); + Quaternion quaternion = Quaternion.LookRotation(new Vector3(x, y, z)); + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction) * quaternion; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.damageTypeOverride = DamageType.Generic; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + if (!NetworkServer.active && (bool)chefController) + { + chefController.CacheCleaverProjectileFireInfo(fireProjectileInfo); + } + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + } + + public override void OnExit() + { + chefController.SetYesChefHeatState(newYesChefHeatState: false); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.boostedFireEffect); + if (!hasBoost) + { + chefController.DestroyCleavers(); + } + } + if (base.isAuthority) + { + chefController.ClearSkillOverrides(); + } + if (chefController.cleaverAway) + { + chefController.recallCleaver = true; + } + if (chefController.catchDirtied) + { + chefController.NetworkcatchDirtied = false; + PlayAnimation("Gesture, Override", "DiceReturnCatch", "DiceReturnCatch.playbackRate", duration); + PlayAnimation("Gesture, Additive", "DiceReturnCatch", "DiceReturnCatch.playbackRate", duration); + } + else + { + PlayAnimation("Gesture, Override", "BufferEmpty", null, duration); + PlayAnimation("Gesture, Additive", "BufferEmpty", null, duration); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + bool flag = base.fixedAge > 0f; + base.FixedUpdate(); + bool flag2 = base.isAuthority; + if (flag) + { + recallInputPressed = base.inputBank.skill1.justPressed; + } + if (recallInputPressed) + { + recallInputPressed = false; + if (chefController.cleaverAway && flag) + { + if (chefController.recallCleaver) + { + chefController.recallCleaver = true; + } + else + { + chefController.recallCleaver = true; + recallBackupCountdown = 3f; + PlayAnimation("Gesture, Override", "DiceReturnHold", null, duration, recallAnimationTransitionTime); + PlayAnimation("Gesture, Additive", "DiceReturnHold", null, duration, recallAnimationTransitionTime); + } + } + } + bool flag3 = false; + if (flag2 && chefController.recallCleaver) + { + recallBackupCountdown -= Time.deltaTime; + if (recallBackupCountdown <= 0f) + { + flag3 = true; + } + } + if (chefController.catchDirtied) + { + if (hasBoost) + { + Util.PlaySound(yesChefReturnString, base.gameObject); + } + else + { + Util.PlaySound(returnString, base.gameObject); + } + if (flag2) + { + outer.SetNextStateToMain(); + } + } + else if (flag3 || (!chefController.cleaverAway && flag)) + { + chefController.NetworkcatchDirtied = true; + if (flag2) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/Glaze.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/Glaze.cs new file mode 100644 index 0000000..b18c31e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/Glaze.cs @@ -0,0 +1,141 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Chef; + +public class Glaze : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public static int grenadeCountMax = 3; + + public static float damageCoefficient; + + public static float fireDuration = 3f; + + public static float baseDuration = 2f; + + public static float arcAngle = 7f; + + public static float recoilAmplitude = 1f; + + public static string attackSoundString; + + public static float spreadBloomValue = 0.3f; + + public static float minimumTimeBetweenShots = 0.025f; + + public static float maximumTimeBetweenShots = 0.1f; + + public static float xDeviationSpread = 1f; + + private Ray projectileRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private int muzzleStringEndNum = 1; + + private void FireGrenade(string targetMuzzle) + { + Util.PlaySound(attackSoundString, base.gameObject); + projectileRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + projectileRay.origin = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + float x = Random.Range(0f, base.characterBody.spreadBloomAngle + xDeviationSpread); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, projectileRay.direction); + Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y = vector.y; + vector.y = 0f; + float angle = Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f + arcAngle; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * projectileRay.direction); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = projectileRay.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(forward); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = 0f; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + fireProjectileInfo.damageTypeOverride = DamageType.WeakOnHit; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + PlayAnimation("Gesture, Override", "ChefGlazeStart", "ChefGlazeStart.playbackRate", duration); + StartAimMode(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + fireTimer -= GetDeltaTime(); + float num = Random.Range(minimumTimeBetweenShots, maximumTimeBetweenShots) + fireDuration / attackSpeedStat / (float)grenadeCountMax; + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + fireTimer += num; + arcAngle = Random.Range(-6, -12); + PlayCrossfade("Gesture, Additive", "ChefGlazeRecoil", 0.2f); + FireGrenade("MuzzleGlaze" + muzzleStringEndNum); + muzzleStringEndNum++; + if (muzzleStringEndNum > 5) + { + muzzleStringEndNum = 1; + } + grenadeCount++; + } + } + if (base.isAuthority && grenadeCount >= grenadeCountMax) + { + PlayCrossfade("Gesture, Override", "ChefGlazeExit", 0.2f); + PlayCrossfade("Gesture, Additive", "ChefGlazeExit", 0.2f); + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/RolyPoly.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/RolyPoly.cs new file mode 100644 index 0000000..2713d21 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/RolyPoly.cs @@ -0,0 +1,392 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Chef; + +public class RolyPoly : GenericCharacterMain +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float speedMultiplier; + + [SerializeField] + public float speedMultiplierLvlUp; + + [SerializeField] + public float baseDurationLvlUp; + + public static float chargeDamageCoefficient; + + public static float chargeDamageCoefficientLvlUp; + + public static float awayForceMagnitude; + + public static float upwardForceMagnitude; + + public static GameObject impactEffectPrefab; + + public static GameObject impactEffectBoostedPrefab; + + public static float hitPauseDuration; + + public static string impactSoundString; + + public static float recoilAmplitude; + + public static string startSoundString; + + public static string endSoundString; + + public static GameObject knockbackEffectPrefab; + + public static float knockbackDamageCoefficient; + + public static float massThresholdForKnockback; + + public static float knockbackForce; + + public static float knockbackForceLvlUp; + + [SerializeField] + public GameObject startEffectPrefab; + + [SerializeField] + public GameObject midEffectPrefab; + + [SerializeField] + public GameObject endEffectPrefab; + + private uint soundID; + + private float duration; + + private float hitPauseTimer; + + private Vector3 idealDirection; + + private OverlapAttack attack; + + private bool inHitPause; + + private int chestIndex = -1; + + private GameObject temporaryInstantiationTransform; + + private GameObject midEffectInstance; + + private float chargeDamageCoefficientTemp; + + private float speedMultiplierTemp; + + private float knockBackForceTemp; + + private float baseDurationTemp; + + private ChefController chefController; + + [SerializeField] + public bool hasBoost; + + [SerializeField] + public float charge; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float whirlwindDamageCo; + + private int originalLayer; + + [SerializeField] + public GameObject rollerSpikePrefab; + + private GameObject rollerSpikeInstance; + + public override void OnEnter() + { + base.OnEnter(); + chefController = base.characterBody.GetComponent(); + chefController.rolyPolyActive = true; + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor?.Motor.RebuildCollidableLayers(); + chargeDamageCoefficientTemp = chargeDamageCoefficient; + knockBackForceTemp = knockbackForce; + speedMultiplierTemp = speedMultiplier; + baseDurationTemp = baseDuration; + float num = charge; + if (num <= 1f) + { + if (num != 0f && num == 1f) + { + chargeDamageCoefficientTemp += chargeDamageCoefficientTemp * chargeDamageCoefficientLvlUp; + speedMultiplierTemp += speedMultiplierTemp * speedMultiplierLvlUp; + knockBackForceTemp += knockBackForceTemp * knockbackForceLvlUp; + baseDurationTemp += baseDurationLvlUp; + } + } + else if (num != 2f) + { + if (num == 3f) + { + chargeDamageCoefficientTemp += chargeDamageCoefficientTemp * (chargeDamageCoefficientLvlUp * 3f); + speedMultiplierTemp += speedMultiplierTemp * (speedMultiplierLvlUp * 3f); + knockBackForceTemp += knockBackForceTemp * (knockbackForceLvlUp * 3f); + baseDurationTemp += baseDurationLvlUp * 3f; + } + } + else + { + chargeDamageCoefficientTemp += chargeDamageCoefficientTemp * (chargeDamageCoefficientLvlUp * 2f); + speedMultiplierTemp += speedMultiplierTemp * (speedMultiplierLvlUp * 2f); + knockBackForceTemp += knockBackForceTemp * (knockbackForceLvlUp * 2f); + baseDurationTemp += baseDurationLvlUp * 2f; + } + if (NetworkServer.active) + { + base.characterBody.AddBuff(DLC2Content.Buffs.CookingRolling); + } + if (hasBoost) + { + Util.PlaySound("Play_chef_skill3_start", base.gameObject); + Util.PlaySound("Play_chef_skill3_boosted_active_loop", base.gameObject); + ProjectileManager.instance.FireProjectile(projectilePrefab, base.gameObject.transform.position, Quaternion.identity, base.gameObject, base.characterBody.damage * whirlwindDamageCo, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + PlayAnimation("Body", "BoostedRolyPoly", "BoostedRolyPoly.playbackRate", 1f); + GetModelAnimator().SetBool("isInBoostedRolyPoly", value: true); + } + else + { + Util.PlaySound("Play_chef_skill3_start", base.gameObject); + GetModelAnimator().SetBool("isInRolyPoly", value: true); + PlayAnimation("Body", "FireRolyPoly", "FireRolyPoly.playbackRate", 1f); + } + duration = baseDurationTemp; + if (base.isAuthority) + { + if ((bool)base.inputBank) + { + idealDirection = base.inputBank.aimDirection; + idealDirection.y = 0f; + } + UpdateDirection(); + } + temporaryInstantiationTransform = GetModelTransform().gameObject; + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = true; + } + if ((bool)base.characterBody) + { + if ((bool)startEffectPrefab) + { + EffectManager.SpawnEffect(startEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: false); + } + if ((bool)midEffectPrefab && (bool)temporaryInstantiationTransform) + { + midEffectInstance = UnityEngine.Object.Instantiate(midEffectPrefab, temporaryInstantiationTransform.transform); + } + } + if ((bool)base.characterDirection) + { + base.characterDirection.forward = idealDirection; + } + Util.PlaySound("Stop_chef_skill3_charge_loop", base.gameObject); + HitBoxGroup hitBoxGroup = null; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Charge"); + } + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = GetTeam(); + attack.damage = chargeDamageCoefficientTemp * damageStat; + attack.hitEffectPrefab = (hasBoost ? impactEffectBoostedPrefab : impactEffectPrefab); + attack.forceVector = Vector3.up * upwardForceMagnitude; + attack.pushAwayForce = knockBackForceTemp; + attack.hitBoxGroup = hitBoxGroup; + attack.isCrit = RollCrit(); + attack.damageType = DamageType.Stun1s; + attack.retriggerTimeout = 0.5f; + } + + private void HandleSpawnRollerspikes() + { + if (!rollerSpikePrefab) + { + return; + } + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + GameObject gameObject = modelChildLocator.FindChildGameObject("Wheel"); + if ((bool)gameObject) + { + rollerSpikeInstance = UnityEngine.Object.Instantiate(rollerSpikePrefab, gameObject.transform); + } + } + } + + private void HandleCleanupRollerSpikes() + { + if ((bool)rollerSpikeInstance) + { + EntityState.Destroy(rollerSpikeInstance); + } + } + + public override void OnExit() + { + chefController.rolyPolyActive = false; + chefController.SetYesChefHeatState(newYesChefHeatState: false); + chefController.blockOtherSkills = false; + if (hasBoost) + { + if (NetworkServer.active && base.characterBody.HasBuff(DLC2Content.Buffs.boostedFireEffect)) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.boostedFireEffect); + } + if (base.isAuthority) + { + chefController.ClearSkillOverrides(); + } + } + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.CookingRolling); + } + base.gameObject.layer = originalLayer; + base.characterMotor?.Motor.RebuildCollidableLayers(); + HandleCleanupRollerSpikes(); + if (!outer.destroying && (bool)base.characterBody) + { + if ((bool)endEffectPrefab) + { + EffectManager.SpawnEffect(endEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: false); + } + if ((bool)midEffectInstance) + { + EntityState.Destroy(midEffectInstance); + } + base.characterBody.isSprinting = false; + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.ArmorBoost); + } + } + if ((bool)base.characterMotor && !base.characterMotor.disableAirControlUntilCollision) + { + base.characterMotor.velocity += GetIdealVelocity(); + } + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = false; + } + GetModelAnimator().SetBool("isInRolyPoly", value: false); + GetModelAnimator().SetBool("isInBoostedRolyPoly", value: false); + PlayCrossfade("Body", "ExitRolyPoly", 0.1f); + AkSoundEngine.StopPlayingID(soundID); + if (hasBoost) + { + Util.PlaySound("Stop_chef_skill3_boosted_active_loop", base.gameObject); + } + Util.PlaySound(endSoundString, base.gameObject); + Util.PlaySound("Stop_chef_skill3_active_loop", base.gameObject); + Util.PlaySound("Stop_chef_skill3_charge_loop", base.gameObject); + base.OnExit(); + } + + private float GetDamageBoostFromSpeed() + { + return Mathf.Max(1f, base.characterBody.moveSpeed / base.characterBody.baseMoveSpeed); + } + + private void UpdateDirection() + { + if ((bool)base.inputBank) + { + Vector3 vector = base.inputBank.moveVector; + Vector2 vector2 = ((!(vector == Vector3.zero)) ? Util.Vector3XZToVector2XY(vector.normalized) : Util.Vector3XZToVector2XY(base.characterDirection.forward)); + if (vector2 != Vector2.zero) + { + vector2.Normalize(); + idealDirection = new Vector3(vector2.x, 0f, vector2.y).normalized; + } + } + } + + private Vector3 GetIdealVelocity() + { + return base.characterDirection.forward.normalized * base.characterBody.moveSpeed * speedMultiplier; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + else + { + if (!base.isAuthority) + { + return; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = true; + } + if ((bool)base.skillLocator.special && base.inputBank.skill4.down) + { + base.skillLocator.special.ExecuteIfReady(); + } + UpdateDirection(); + if (!inHitPause) + { + if ((bool)base.characterDirection) + { + base.characterMotor.moveDirection = idealDirection; + base.characterDirection.moveVector = idealDirection; + if ((bool)base.characterMotor && !base.characterMotor.disableAirControlUntilCollision) + { + base.characterMotor.rootMotion += GetIdealVelocity() * GetDeltaTime(); + } + } + if (attack.Fire()) + { + inHitPause = true; + hitPauseTimer = hitPauseDuration; + AddRecoil(-0.25f * recoilAmplitude, -0.25f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + } + } + else + { + base.characterMotor.velocity = Vector3.zero; + hitPauseTimer -= GetDeltaTime(); + if (hitPauseTimer < 0f) + { + inHitPause = false; + } + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/RolyPolyWeaponBlockingState.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/RolyPolyWeaponBlockingState.cs new file mode 100644 index 0000000..2a9c630 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/RolyPolyWeaponBlockingState.cs @@ -0,0 +1,26 @@ +namespace EntityStates.Chef; + +public class RolyPolyWeaponBlockingState : BaseSkillState +{ + private ChefController chefController; + + public override void OnEnter() + { + base.OnEnter(); + chefController = base.characterBody.GetComponent(); + } + + public override void Update() + { + base.Update(); + if (base.isAuthority && !chefController.blockOtherSkills) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/Sear.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/Sear.cs new file mode 100644 index 0000000..aeba5e2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/Sear.cs @@ -0,0 +1,338 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Chef; + +public class Sear : BaseState +{ + public static GameObject flamethrowerEffectPrefab; + + public static GameObject ovenBlueEffectPrefab; + + public static GameObject initialOvenBlueEffectPrefab; + + public static GameObject boostedSearProjectilePrefab; + + public static GameObject impactEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float maxDistance; + + public static float radius; + + public static float baseEntryDuration = 1f; + + public static float baseExitDuration = 0.5f; + + public static float baseFlamethrowerDuration = 2f; + + public static float totalDamageCoefficient = 1.2f; + + public static float procCoefficientPerTick; + + public static float tickFrequency; + + public static float force = 20f; + + public static GameObject muzzleflashEffectPrefab; + + public static float boostedProjectileDmgCoefficient = 1f; + + public static float boostedProjectileCount = 1f; + + public static float boostedProjectileTimer; + + public static float boostedProjectileInBetweenShotTime; + + public static string startAttackSoundString; + + public static string endAttackSoundString; + + public static string endLoopSoundString; + + public static string boostedStartAttackSoundString; + + public static string boostedEndAttackSoundString; + + public static string boostedEndLoopSoundString; + + public static string boostedFireBallSoundString; + + public static float ignitePercentChance; + + public static float maxSpread; + + private float tickDamageCoefficient; + + private float primaryAttackStopwatch; + + private float stopwatch; + + private float entryDuration; + + private float exitDuration; + + private float flamethrowerDuration; + + private bool flamethrowerStarted; + + private bool flamethrowerEnded; + + private ChildLocator childLocator; + + private Transform flamethrowerEffectInstance; + + private Transform muzzleTransform; + + private bool isCrit; + + private bool hasBoost; + + private float boostedDamage; + + private int boostedProjectilesFired; + + private bool allBoostProjectilesFired; + + private ChefController chefController; + + private const float flamethrowerEffectBaseDistance = 16f; + + private float flamethrowerTimestamp; + + public override void OnEnter() + { + base.OnEnter(); + chefController = GetComponent(); + if (NetworkServer.active) + { + base.characterBody.AddBuff(DLC2Content.Buffs.CookingSearing); + } + if (base.characterBody.HasBuff(DLC2Content.Buffs.Boosted)) + { + hasBoost = true; + base.characterBody.RemoveBuff(DLC2Content.Buffs.Boosted); + } + stopwatch = 0f; + entryDuration = baseEntryDuration / attackSpeedStat; + exitDuration = baseExitDuration / attackSpeedStat; + flamethrowerDuration = baseFlamethrowerDuration + exitDuration; + Transform modelTransform = GetModelTransform(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(entryDuration + flamethrowerDuration + 1f); + } + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + modelTransform.GetComponent().enabled = true; + muzzleTransform = childLocator.FindChild("MuzzleCenter"); + } + float num = flamethrowerDuration * tickFrequency; + if (hasBoost) + { + boostedDamage = 1.5f; + } + else + { + boostedDamage = 1f; + } + tickDamageCoefficient = totalDamageCoefficient * boostedDamage / num; + if (base.isAuthority && (bool)base.characterBody) + { + isCrit = Util.CheckRoll(critStat, base.characterBody.master); + } + boostedProjectileTimer = boostedProjectileInBetweenShotTime; + PlayAnimation("Gesture, Additive", "PrepSear", "PrepSear.playbackRate", entryDuration); + PlayAnimation("Gesture, Override", "PrepSear", "PrepSear.playbackRate", entryDuration); + } + + public override void Update() + { + base.Update(); + float deltaTime = Time.deltaTime; + stopwatch += deltaTime; + if (stopwatch < entryDuration) + { + return; + } + if (hasBoost && !allBoostProjectilesFired) + { + HandleBoostProjectiles(deltaTime); + return; + } + if (!flamethrowerStarted && stopwatch >= entryDuration) + { + StartPrimaryFlameVFX(); + } + else if (!flamethrowerEnded) + { + if (base.isAuthority) + { + HandlePrimaryAttack(deltaTime); + } + if (stopwatch >= entryDuration + flamethrowerDuration) + { + EndPrimaryFlameVFX(); + } + } + if (flamethrowerEnded && stopwatch >= flamethrowerDuration + entryDuration + exitDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void HandleBoostProjectiles(float deltaTime) + { + boostedProjectileTimer += deltaTime; + if (!(boostedProjectileTimer < boostedProjectileInBetweenShotTime)) + { + if ((float)boostedProjectilesFired < boostedProjectileCount) + { + boostedProjectileTimer = 0f; + boostedProjectilesFired++; + FireBoostedFireball("MuzzleCenter"); + } + else + { + allBoostProjectilesFired = true; + stopwatch = entryDuration; + } + } + } + + private void FirePrimaryAttack(string muzzleString) + { + GetAimRay(); + if (base.isAuthority && (bool)muzzleTransform) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = muzzleTransform.position; + bulletAttack.aimVector = muzzleTransform.forward; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = maxSpread; + bulletAttack.damage = tickDamageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.muzzleName = muzzleString; + bulletAttack.hitEffectPrefab = impactEffectPrefab; + bulletAttack.isCrit = isCrit; + bulletAttack.radius = radius; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.stopperMask = LayerIndex.world.mask; + bulletAttack.procCoefficient = procCoefficientPerTick; + bulletAttack.maxDistance = maxDistance; + bulletAttack.smartCollision = true; + bulletAttack.damageType = new DamageTypeCombo(DamageType.IgniteOnHit, DamageTypeExtended.ChefSearDamage); + bulletAttack.Fire(); + } + } + + private void FireBoostedFireball(string muzzleString) + { + if (base.isAuthority && (bool)muzzleTransform) + { + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + } + Ray aimRay = GetAimRay(); + Util.PlaySound(boostedFireBallSoundString, base.gameObject); + ProjectileManager.instance.FireProjectile(boostedSearProjectilePrefab, muzzleTransform.position, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, base.characterBody.damage * boostedProjectileDmgCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + private void StartPrimaryFlameVFX() + { + flamethrowerStarted = true; + PlayAnimation("Gesture, Override", "FireSear", "FireSear.playbackRate", flamethrowerDuration); + PlayAnimation("Gesture, Additive", "FireSear", "FireSear.playbackRate", flamethrowerDuration); + if (hasBoost) + { + flamethrowerEffectInstance = Object.Instantiate(ovenBlueEffectPrefab, muzzleTransform).transform; + Util.PlaySound(boostedStartAttackSoundString, base.gameObject); + } + else + { + flamethrowerEffectInstance = Object.Instantiate(flamethrowerEffectPrefab, muzzleTransform).transform; + Util.PlaySound(startAttackSoundString, base.gameObject); + } + flamethrowerTimestamp = Time.time; + flamethrowerEffectInstance.transform.localPosition = Vector3.zero; + flamethrowerEffectInstance.GetComponent().newDuration = flamethrowerDuration; + } + + private void EndPrimaryFlameVFX() + { + flamethrowerEnded = true; + PlayCrossfade("Gesture, Override", "ExitSear", "ExitSear.playbackRate", exitDuration, 0.1f); + PlayCrossfade("Gesture, Additive", "ExitSear", "ExitSear.playbackRate", exitDuration, 0.1f); + if ((bool)flamethrowerEffectInstance) + { + if (hasBoost) + { + Util.PlaySound(boostedEndLoopSoundString, base.gameObject); + Util.PlaySound(boostedEndAttackSoundString, base.gameObject); + } + else + { + Util.PlaySound(endLoopSoundString, base.gameObject); + Util.PlaySound(endAttackSoundString, base.gameObject); + } + EntityState.Destroy(flamethrowerEffectInstance.gameObject); + } + } + + private void HandlePrimaryAttack(float deltaTime) + { + primaryAttackStopwatch += deltaTime; + if (primaryAttackStopwatch > 1f / tickFrequency) + { + primaryAttackStopwatch -= 1f / tickFrequency; + FirePrimaryAttack("MuzzleCenter"); + } + } + + public override void OnExit() + { + chefController.SetYesChefHeatState(newYesChefHeatState: false); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.CookingSearing); + if (base.characterBody.HasBuff(DLC2Content.Buffs.boostedFireEffect)) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.boostedFireEffect); + } + } + if (base.isAuthority) + { + chefController.ClearSkillOverrides(); + } + PlayCrossfade("Gesture, Override", "BufferEmpty", 0.1f); + PlayCrossfade("Gesture, Additive", "BufferEmpty", 0.1f); + if ((bool)flamethrowerEffectInstance) + { + if (hasBoost) + { + Util.PlaySound(boostedEndLoopSoundString, base.gameObject); + Util.PlaySound(boostedEndAttackSoundString, base.gameObject); + } + else + { + Util.PlaySound(endLoopSoundString, base.gameObject); + Util.PlaySound(endAttackSoundString, base.gameObject); + } + EntityState.Destroy(flamethrowerEffectInstance.gameObject); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Chef/YesChef.cs b/ilspy_dump/ror2_csproj/EntityStates.Chef/YesChef.cs new file mode 100644 index 0000000..3a9e1b0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Chef/YesChef.cs @@ -0,0 +1,173 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Chef; + +public class YesChef : BaseState +{ + [SerializeField] + public float duration = 1f; + + [SerializeField] + public GameObject playerRespawnEffectPrefab; + + [SerializeField] + public string startSoundString; + + [SerializeField] + public int buffStockToAdd = 3; + + [SerializeField] + public float heatDamageCo = 1f; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject blastEffectPrefab; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastRadius; + + [SerializeField] + public float blastProcCoefficient; + + [SerializeField] + public float blastForce; + + [SerializeField] + [Tooltip("Set This to the child transform you want the blast effect to parent to")] + public string blastEffectTransformChild; + + [SerializeField] + public float exitDelay; + + [SerializeField] + public SkillDef primarySkillOverrideDef; + + [SerializeField] + public SkillDef secondarySkillOverrideDef; + + [SerializeField] + public SkillDef utilitySkillOverrideDef; + + [SerializeField] + public SkillDef specialSkillOverrideDef; + + private bool alreadyRan; + + private ChildLocator childLocator; + + private ChefController chefController; + + private bool playedYesChefSFX; + + public override void OnEnter() + { + base.OnEnter(); + chefController = base.characterBody.GetComponent(); + if ((bool)chefController) + { + chefController.SetYesChefHeatState(newYesChefHeatState: true); + } + if (base.isAuthority && (bool)chefController) + { + chefController.ClearSkillOverrides(); + SkillStateOverrideData skillStateOverrideData = new SkillStateOverrideData(base.characterBody, _duplicateStock: true); + skillStateOverrideData.simulateRestockForOverridenSkills = false; + skillStateOverrideData.primarySkillOverride = primarySkillOverrideDef; + skillStateOverrideData.secondarySkillOverride = secondarySkillOverrideDef; + skillStateOverrideData.utilitySkillOverride = utilitySkillOverrideDef; + skillStateOverrideData.specialSkillOverride = specialSkillOverrideDef; + skillStateOverrideData.OverrideSkills(base.skillLocator); + EnsureMinStock(ref base.skillLocator.primary); + EnsureMinStock(ref base.skillLocator.secondary); + EnsureMinStock(ref base.skillLocator.utility); + chefController.TransferSkillOverrides(skillStateOverrideData); + } + childLocator = GetModelChildLocator(); + PlayAnimation("Gesture, Additive", "FireYesChef", "FireYesChef.playbackRate", duration); + PlayAnimation("Gesture, Override", "FireYesChef", "FireYesChef.playbackRate", duration); + EffectData effectData = new EffectData + { + origin = base.transform.position, + scale = blastRadius + }; + if ((bool)childLocator) + { + int num = childLocator.FindChildIndex(blastEffectTransformChild); + if (num != -1) + { + effectData.SetChildLocatorTransformReference(base.gameObject, num); + } + } + EffectManager.SpawnEffect(blastEffectPrefab, effectData, transmit: true); + chefController.ActivateServoStrainSfxForDuration(3f); + static void EnsureMinStock(ref GenericSkill skill) + { + if (skill.stock < 1) + { + skill.stock = 1; + skill.rechargeStopwatch = 0f; + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnExit() + { + base.OnExit(); + if (NetworkServer.active) + { + if (!base.characterBody.HasBuff(DLC2Content.Buffs.Boosted)) + { + base.characterBody.AddBuff(DLC2Content.Buffs.Boosted); + } + if (!base.characterBody.HasBuff(DLC2Content.Buffs.boostedFireEffect)) + { + base.characterBody.AddBuff(DLC2Content.Buffs.boostedFireEffect); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > 0.5f && !playedYesChefSFX) + { + Util.PlaySound(startSoundString, base.gameObject); + playedYesChefSFX = true; + } + if ((bool)chefController && base.fixedAge > duration && base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, base.gameObject.transform.position, Quaternion.identity, base.gameObject, base.characterBody.damage * heatDamageCo, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + Util.PlaySound("Play_chef_skill4_flame_aoe_on", base.gameObject); + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.characterBody.gameObject; + blastAttack.baseDamage = blastDamageCoefficient * base.characterBody.damage; + blastAttack.baseForce = blastForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.crit = base.characterBody.RollCrit(); + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.inflictor = base.gameObject; + blastAttack.position = base.characterBody.corePosition; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = blastProcCoefficient; + blastAttack.radius = blastRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.teamIndex = base.teamComponent.teamIndex; + blastAttack.Fire(); + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/DeathState.cs new file mode 100644 index 0000000..d946471 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/DeathState.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ChildMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathEffectPrefab; + + public float smallHopVelocity = 0.35f; + + private bool blewUp; + + public float duration = 0.2f; + + public static string deathSoundString; + + public override void OnEnter() + { + base.OnEnter(); + SmallHop(base.characterMotor, smallHopVelocity); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && !blewUp && base.fixedAge > duration) + { + EffectManager.SpawnEffect(deathEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: true); + Util.PlaySound(deathSoundString, base.gameObject); + blewUp = true; + } + if (base.fixedAge > duration * 2f) + { + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/Frolic.cs b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/Frolic.cs new file mode 100644 index 0000000..b5bd4a6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/Frolic.cs @@ -0,0 +1,126 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.CharacterAI; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.ChildMonster; + +public class Frolic : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static GameObject tpEffectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string attackString; + + public static float tpDuration = 0.5f; + + public static float fireFrolicDuration = 0.3f; + + public static float frolicCooldownDuration = 18f; + + private float duration; + + private bool frolicFireFired; + + private bool tpFired; + + private bool cantFrolic; + + public override void OnEnter() + { + base.OnEnter(); + ChildMonsterController component = base.characterBody.GetComponent(); + cantFrolic = !component.CheckTeleportAvailable(); + if (!cantFrolic) + { + component.RegisterTeleport(); + fireFrolicDuration += tpDuration; + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Override", "FrolicEnter", "FrolicEnter.playbackRate", 1f); + Util.PlaySound(attackString, base.gameObject); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (cantFrolic) + { + outer.SetNextStateToMain(); + return; + } + if (base.fixedAge > tpDuration && !tpFired) + { + FireTPEffect(); + tpFired = true; + TeleportAroundPlayer(); + } + if (base.fixedAge > fireFrolicDuration && !frolicFireFired) + { + frolicFireFired = true; + FireTPEffect(); + Transform transform = base.characterBody.master.GetComponent().currentEnemy.characterBody.transform; + base.characterBody.transform.LookAt(transform.position); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public void TeleportAroundPlayer() + { + GetComponent().modelTransform.GetComponent(); + _ = base.characterBody.corePosition; + NodeGraph nodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + Vector3 position = base.characterBody.master.GetComponent().currentEnemy.characterBody.coreTransform.position; + List list = nodeGraph.FindNodesInRange(position, 25f, 37f, HullMask.Human); + Vector3 position2 = default(Vector3); + bool flag = false; + int num = 35; + while (!flag) + { + NodeGraph.NodeIndex nodeIndex = list.ElementAt(Random.Range(1, list.Count)); + nodeGraph.GetNodePosition(nodeIndex, out position2); + float num2 = Vector3.Distance(base.characterBody.coreTransform.position, position2); + num--; + if (num2 > 35f || num < 0) + { + flag = true; + } + } + if (num < 0) + { + Debug.LogWarning("Child.Frolic state entered a loop where it ran more than 35 times without getting out - check what it's doing"); + } + position2 += Vector3.up * 1.5f; + TeleportHelper.TeleportBody(base.characterBody, position2); + } + + public void FireTPEffect() + { + Vector3 position = FindModelChild("Chest").transform.position; + EffectManager.SpawnEffect(tpEffectPrefab, new EffectData + { + origin = position, + scale = 1f + }, transmit: true); + Util.PlaySound("Play_child_attack2_reappear", base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/FrolicAway.cs b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/FrolicAway.cs new file mode 100644 index 0000000..ee5b3e8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/FrolicAway.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.ChildMonster; + +public class FrolicAway : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static GameObject tpEffectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string attackString; + + public static float tpDuration = 0.5f; + + public static float fireFrolicDuration = 0.3f; + + private float duration; + + private bool frolicFireFired; + + private bool tpFired; + + public override void OnEnter() + { + base.OnEnter(); + fireFrolicDuration += tpDuration; + base.characterBody.GetComponent()?.RegisterTeleport(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Override", "FrolicEnter", "FrolicEnter.playbackRate", 1f); + Util.PlaySound(attackString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > tpDuration && !tpFired) + { + FireTPEffect(); + tpFired = true; + TeleportAway(); + } + if (base.fixedAge > fireFrolicDuration && !frolicFireFired) + { + frolicFireFired = true; + FireTPEffect(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public void TeleportAway() + { + CharacterModel component = GetComponent().modelTransform.GetComponent(); + _ = base.characterBody.corePosition; + NodeGraph nodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + List source = nodeGraph.FindNodesInRange(base.characterBody.corePosition, 100f, 200f, HullMask.Human); + nodeGraph.GetNodePosition(source.First(), out var position); + TeleportHelper.TeleportBody(base.characterBody, position); + TeleportOutController.AddTPOutEffect(component, 1f, 0f, 1f); + if ((bool)tpEffectPrefab) + { + FireTPEffect(); + } + } + + public void FireTPEffect() + { + Vector3 position = FindModelChild("Chest").transform.position; + EffectManager.SpawnEffect(tpEffectPrefab, new EffectData + { + origin = position, + scale = 1f + }, transmit: true); + Util.PlaySound("Play_child_attack2_reappear", base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SparkBallCharge.cs b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SparkBallCharge.cs new file mode 100644 index 0000000..6530148 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SparkBallCharge.cs @@ -0,0 +1,71 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ChildMonster; + +public class SparkBallCharge : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargingEffectPrefab; + + public static string chargingSoundString; + + private float duration; + + private float stopwatch; + + private GameObject chargeEffectInstance; + + private uint soundID; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayCrossfade("Gesture, Override", "SparkEnter", "SparkEnter.playbackRate", duration, 0.3f); + soundID = Util.PlayAttackSpeedSound(chargingSoundString, base.gameObject, attackSpeedStat); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleFire"); + if ((bool)transform && (bool)chargingEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargingEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + chargeEffectInstance.GetComponent().newDuration = duration; + } + } + } + + public override void OnExit() + { + base.OnExit(); + AkSoundEngine.StopPlayingID(soundID); + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextState(new SparkBallFire()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SparkBallFire.cs b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SparkBallFire.cs new file mode 100644 index 0000000..26c2a94 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SparkBallFire.cs @@ -0,0 +1,69 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ChildMonster; + +public class SparkBallFire : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject projectilePrefab; + + public static GameObject muzzleEffectPrefab; + + public static string fireBombSoundString; + + public static float bombDamageCoefficient; + + public static float bombForce; + + public float novaRadius; + + private float duration; + + private float stopwatch; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Override", "SparkLaunch", "SparkLaunch.playbackRate", duration); + FireBomb(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireBomb() + { + Ray aimRay = GetAimRay(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + aimRay.origin = component.FindChild("MuzzleFire").transform.position; + } + } + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "MuzzleFire", transmit: false); + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * bombDamageCoefficient, bombForce, Util.CheckRoll(critStat, base.characterBody.master)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SpawnState.cs new file mode 100644 index 0000000..b6089de --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ChildMonster/SpawnState.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ChildMonster; + +public class SpawnState : EntityState +{ + public static float duration = 1f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private ParentEnergyFXController FXController; + + public override void OnEnter() + { + base.OnEnter(); + GetModelAnimator(); + PlayAnimation("Gesture, Override", "FrolicEnter", "FrolicEnter.playbackRate", duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SpawnEffect(spawnEffectPrefab, new EffectData + { + origin = base.gameObject.transform.position + }, transmit: true); + } + PrintController component = base.modelLocator.modelTransform.gameObject.GetComponent(); + component.enabled = false; + component.printTime = duration; + component.startingPrintHeight = 4f; + component.maxPrintHeight = -1f; + component.startingPrintBias = 2f; + component.maxPrintBias = 0.95f; + component.disableWhenFinished = true; + component.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + component.enabled = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss.ClayBossWeapon/ChargeBombardment.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss.ClayBossWeapon/ChargeBombardment.cs new file mode 100644 index 0000000..7763121 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss.ClayBossWeapon/ChargeBombardment.cs @@ -0,0 +1,133 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBoss.ClayBossWeapon; + +public class ChargeBombardment : BaseState +{ + public static float baseTotalDuration; + + public static float baseMaxChargeTime; + + public static int maxCharges; + + public static GameObject chargeEffectPrefab; + + public static string chargeLoopStartSoundString; + + public static string chargeLoopStopSoundString; + + public static int minGrenadeCount; + + public static int maxGrenadeCount; + + public static float minBonusBloom; + + public static float maxBonusBloom; + + private float stopwatch; + + private GameObject chargeInstance; + + private int charge; + + private float totalDuration; + + private float maxChargeTime; + + private EffectManagerHelper _emh_chargeInstance; + + private static int ChargeBombardmentStateHash = Animator.StringToHash("ChargeBombardment"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + public override void Reset() + { + base.Reset(); + stopwatch = 0f; + chargeInstance = null; + charge = 0; + totalDuration = 0f; + maxChargeTime = 0f; + _emh_chargeInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + totalDuration = baseTotalDuration / attackSpeedStat; + maxChargeTime = baseMaxChargeTime / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayAnimation("Gesture, Additive", ChargeBombardmentStateHash); + Util.PlaySound(chargeLoopStartSoundString, base.gameObject); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("Muzzle"); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance = _emh_chargeInstance.gameObject; + } + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = totalDuration; + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(totalDuration); + } + } + + public override void OnExit() + { + base.OnExit(); + PlayAnimation("Gesture, Additive", EmptyStateHash); + Util.PlaySound(chargeLoopStopSoundString, base.gameObject); + if (_emh_chargeInstance != null && _emh_chargeInstance.OwningPool != null) + { + _emh_chargeInstance.OwningPool.ReturnObject(_emh_chargeInstance); + } + else + { + EntityState.Destroy(chargeInstance); + } + _emh_chargeInstance = null; + chargeInstance = null; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + charge = Mathf.Min((int)(stopwatch / maxChargeTime * (float)maxCharges), maxCharges); + float t = (float)charge / (float)maxCharges; + float value = Mathf.Lerp(minBonusBloom, maxBonusBloom, t); + base.characterBody.SetSpreadBloom(value); + int grenadeCountMax = Mathf.FloorToInt(Mathf.Lerp(minGrenadeCount, maxGrenadeCount, t)); + if ((stopwatch >= totalDuration || !base.inputBank || !base.inputBank.skill1.down) && base.isAuthority) + { + FireBombardment fireBombardment = new FireBombardment(); + fireBombardment.grenadeCountMax = grenadeCountMax; + outer.SetNextState(fireBombardment); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss.ClayBossWeapon/FireBombardment.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss.ClayBossWeapon/FireBombardment.cs new file mode 100644 index 0000000..6a5704f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss.ClayBossWeapon/FireBombardment.cs @@ -0,0 +1,136 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ClayBoss.ClayBossWeapon; + +public class FireBombardment : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public int grenadeCountMax = 3; + + public static float damageCoefficient; + + public static float baseTimeBetweenShots = 1f; + + public static float cooldownDuration = 2f; + + public static float arcAngle = 5f; + + public static float recoilAmplitude = 1f; + + public static string shootSoundString; + + public static float spreadBloomValue = 0.3f; + + private Ray aimRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private float timeBetweenShots; + + private void FireGrenade(string targetMuzzle) + { + PlayCrossfade("Gesture, Bombardment", "FireBombardment", 0.1f); + Util.PlaySound(shootSoundString, base.gameObject); + aimRay = GetAimRay(); + Vector3 vector = aimRay.origin; + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + vector = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: true); + } + if (base.isAuthority) + { + float num = -1f; + if (Util.CharacterRaycast(base.gameObject, aimRay, out var hitInfo, float.PositiveInfinity, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + Vector3 point = hitInfo.point; + float velocity = projectilePrefab.GetComponent().velocity; + Vector3 vector2 = point - vector; + Vector2 vector3 = new Vector2(vector2.x, vector2.z); + float magnitude = vector3.magnitude; + float y = Trajectory.CalculateInitialYSpeed(magnitude / velocity, vector2.y); + Vector3 vector4 = new Vector3(vector3.x / magnitude * velocity, y, vector3.y / magnitude * velocity); + num = vector4.magnitude; + aimRay.direction = vector4 / num; + } + float x = Random.Range(0f, base.characterBody.spreadBloomAngle); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, aimRay.direction); + Vector3 vector5 = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y2 = vector5.y; + vector5.y = 0f; + float angle = Mathf.Atan2(vector5.z, vector5.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y2, vector5.magnitude) * 57.29578f; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * aimRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, vector, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, num); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + timeBetweenShots = baseTimeBetweenShots / attackSpeedStat; + duration = (baseTimeBetweenShots * (float)grenadeCount + cooldownDuration) / attackSpeedStat; + PlayCrossfade("Gesture, Additive", "BeginBombardment", 0.1f); + modelTransform = GetModelTransform(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + PlayCrossfade("Gesture, Additive", "EndBombardment", 0.1f); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + fireTimer += timeBetweenShots; + FireGrenade("Muzzle"); + grenadeCount++; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/DeathState.cs new file mode 100644 index 0000000..3ea4b8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/DeathState.cs @@ -0,0 +1,128 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ClayBoss; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialEffect; + + public static GameObject deathEffect; + + public static float duration = 2f; + + private float stopwatch; + + private Transform modelBaseTransform; + + private Transform centerTransform; + + private EffectData _effectData; + + private EffectManagerHelper _emh_initialEffect; + + private bool attemptedDeathBehavior; + + public override void Reset() + { + base.Reset(); + stopwatch = 0f; + modelBaseTransform = null; + centerTransform = null; + attemptedDeathBehavior = false; + if (_effectData != null) + { + _effectData.Reset(); + } + _emh_initialEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + if (!base.modelLocator) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + centerTransform = component.FindChild("Center"); + if ((bool)initialEffect) + { + if (!EffectManager.ShouldUsePooledEffect(initialEffect)) + { + GameObject obj = Object.Instantiate(initialEffect, centerTransform.position, centerTransform.rotation); + obj.GetComponent().newDuration = duration; + obj.transform.parent = centerTransform; + } + else + { + _emh_initialEffect = EffectManager.GetAndActivatePooledEffect(initialEffect, centerTransform.position, centerTransform.rotation, centerTransform); + _emh_initialEffect.gameObject.GetComponent().newDuration = duration; + } + } + } + modelBaseTransform = base.modelLocator.modelBaseTransform; + } + + private void AttemptDeathBehavior() + { + if (attemptedDeathBehavior) + { + return; + } + attemptedDeathBehavior = true; + CleanupInitialEffect(); + if ((bool)deathEffect && NetworkServer.active) + { + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.origin = centerTransform.position; + EffectManager.SpawnEffect(deathEffect, _effectData, transmit: true); + } + if ((bool)modelBaseTransform) + { + EntityState.Destroy(modelBaseTransform.gameObject); + modelBaseTransform = null; + } + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } + + public override void FixedUpdate() + { + stopwatch += GetDeltaTime(); + if (stopwatch >= duration) + { + AttemptDeathBehavior(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + AttemptDeathBehavior(); + } + else + { + CleanupInitialEffect(); + } + base.OnExit(); + } + + public void CleanupInitialEffect() + { + if (_emh_initialEffect != null && _emh_initialEffect.OwningPool != null) + { + _emh_initialEffect.OwningPool.ReturnObject(_emh_initialEffect); + _emh_initialEffect = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/FireTarball.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/FireTarball.cs new file mode 100644 index 0000000..0fb694a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/FireTarball.cs @@ -0,0 +1,114 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ClayBoss; + +public class FireTarball : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public static int tarballCountMax = 3; + + public static float damageCoefficient; + + public static float baseTimeBetweenShots = 1f; + + public static float cooldownDuration = 2f; + + public static float recoilAmplitude = 1f; + + public static string attackSoundString; + + public static float spreadBloomValue = 0.3f; + + private int tarballCount; + + private Ray aimRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private float timeBetweenShots; + + private void FireSingleTarball(string targetMuzzle) + { + PlayCrossfade("Body", "FireTarBall", 0.1f); + Util.PlaySound(attackSoundString, base.gameObject); + aimRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + aimRay.origin = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: true); + } + if (base.isAuthority) + { + Vector3 forward = Vector3.ProjectOnPlane(aimRay.direction, Vector3.up); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + timeBetweenShots = baseTimeBetweenShots / attackSpeedStat; + duration = (baseTimeBetweenShots * (float)tarballCountMax + cooldownDuration) / attackSpeedStat; + modelTransform = GetModelTransform(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + if (tarballCount < tarballCountMax) + { + fireTimer += timeBetweenShots; + FireSingleTarball("BottomMuzzle"); + tarballCount++; + } + else + { + fireTimer += 9999f; + PlayCrossfade("Body", "ExitTarBall", "ExitTarBall.playbackRate", (cooldownDuration - baseTimeBetweenShots) / attackSpeedStat, 0.1f); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/PrepTarBall.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/PrepTarBall.cs new file mode 100644 index 0000000..2a4bc64 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/PrepTarBall.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBoss; + +public class PrepTarBall : BaseState +{ + public static float baseDuration = 3f; + + public static string prepTarBallSoundString; + + private float duration; + + private float stopwatch; + + private Animator modelAnimator; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayCrossfade("Body", "PrepTarBall", "PrepTarBall.playbackRate", duration, 0.5f); + } + if (!string.IsNullOrEmpty(prepTarBallSoundString)) + { + Util.PlayAttackSpeedSound(prepTarBallSoundString, base.gameObject, attackSpeedStat); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextState(new FireTarball()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/Recover.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/Recover.cs new file mode 100644 index 0000000..325133a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/Recover.cs @@ -0,0 +1,257 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ClayBoss; + +public class Recover : BaseState +{ + private enum SubState + { + Entry, + Tethers + } + + public static float duration = 15f; + + public static float maxTetherDistance = 40f; + + public static float tetherMulchDistance = 5f; + + public static float tetherMulchDamageScale = 2f; + + public static float tetherMulchTickIntervalScale = 0.5f; + + public static float damagePerSecond = 2f; + + public static float damageTickFrequency = 3f; + + public static float entryDuration = 1f; + + public static GameObject mulchEffectPrefab; + + public static string enterSoundString; + + public static string beginMulchSoundString; + + public static string stopMulchSoundString; + + private GameObject mulchEffect; + + private Transform muzzleTransform; + + private List tetherControllers; + + private List victimsList; + + private BullseyeSearch search; + + private float stopwatch; + + private uint soundID; + + private EffectManagerHelper _emh_mulchEffect; + + private SubState subState; + + private static int ChannelSiphonStateHash = Animator.StringToHash("ChannelSiphon"); + + public override void Reset() + { + base.Reset(); + mulchEffect = null; + muzzleTransform = null; + if (tetherControllers != null) + { + tetherControllers.Clear(); + } + if (victimsList != null) + { + victimsList.Clear(); + } + if (search != null) + { + search.Reset(); + } + soundID = 0u; + subState = SubState.Entry; + _emh_mulchEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.AddBuff(RoR2Content.Buffs.ArmorBoost); + } + if ((bool)base.modelLocator) + { + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild("MuzzleMulch"); + } + } + subState = SubState.Entry; + PlayCrossfade("Body", "PrepSiphon", "PrepSiphon.playbackRate", entryDuration, 0.1f); + soundID = Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + } + + private void FireTethers() + { + Vector3 position = muzzleTransform.position; + float breakDistanceSqr = maxTetherDistance * maxTetherDistance; + if (victimsList == null) + { + victimsList = new List(); + } + tetherControllers = new List(); + if (search == null) + { + search = new BullseyeSearch(); + } + search.searchOrigin = position; + search.maxDistanceFilter = maxTetherDistance; + search.teamMaskFilter = TeamMask.allButNeutral; + search.sortMode = BullseyeSearch.SortMode.Distance; + search.filterByLoS = true; + search.searchDirection = Vector3.up; + search.RefreshCandidates(); + search.FilterOutGameObject(base.gameObject); + List list = search.GetResults().ToList(); + for (int i = 0; i < list.Count; i++) + { + GameObject gameObject = list[i].healthComponent.gameObject; + if ((bool)gameObject) + { + victimsList.Add(gameObject); + } + } + float tickInterval = 1f / damageTickFrequency; + float damageCoefficientPerTick = damagePerSecond / damageTickFrequency; + float mulchDistanceSqr = tetherMulchDistance * tetherMulchDistance; + GameObject original = LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/TarTether"); + for (int j = 0; j < victimsList.Count; j++) + { + GameObject obj = Object.Instantiate(original, position, Quaternion.identity); + TarTetherController component = obj.GetComponent(); + component.NetworkownerRoot = base.gameObject; + component.NetworktargetRoot = victimsList[j]; + component.breakDistanceSqr = breakDistanceSqr; + component.damageCoefficientPerTick = damageCoefficientPerTick; + component.tickInterval = tickInterval; + component.tickTimer = (float)j * 0.1f; + component.mulchDistanceSqr = mulchDistanceSqr; + component.mulchDamageScale = tetherMulchDamageScale; + component.mulchTickIntervalScale = tetherMulchTickIntervalScale; + tetherControllers.Add(component); + NetworkServer.Spawn(obj); + } + } + + private void DestroyTethers() + { + if (tetherControllers == null) + { + return; + } + for (int num = tetherControllers.Count - 1; num >= 0; num--) + { + if ((bool)tetherControllers[num]) + { + EntityState.Destroy(tetherControllers[num].gameObject); + } + } + } + + public override void OnExit() + { + DestroyTethers(); + if ((bool)mulchEffect) + { + if ((bool)_emh_mulchEffect && _emh_mulchEffect.OwningPool != null) + { + _emh_mulchEffect.ReturnToPool(); + _emh_mulchEffect = null; + } + else + { + EntityState.Destroy(mulchEffect); + } + } + AkSoundEngine.StopPlayingID(soundID); + Util.PlaySound(stopMulchSoundString, base.gameObject); + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.ArmorBoost); + } + base.OnExit(); + } + + private static void RemoveDeadTethersFromList(List tethersList) + { + for (int num = tethersList.Count - 1; num >= 0; num--) + { + if (!tethersList[num]) + { + tethersList.RemoveAt(num); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (subState == SubState.Entry) + { + if (stopwatch >= entryDuration) + { + subState = SubState.Tethers; + stopwatch = 0f; + PlayAnimation("Body", ChannelSiphonStateHash); + Util.PlaySound(beginMulchSoundString, base.gameObject); + SpawnMulcherEffect(); + if (NetworkServer.active) + { + FireTethers(); + } + } + } + else if (subState == SubState.Tethers && NetworkServer.active) + { + RemoveDeadTethersFromList(tetherControllers); + if ((stopwatch >= duration || tetherControllers.Count == 0) && base.isAuthority) + { + outer.SetNextState(new RecoverExit()); + } + } + } + + private void SpawnMulcherEffect() + { + if (!EffectManager.ShouldUsePooledEffect(mulchEffectPrefab)) + { + mulchEffect = Object.Instantiate(mulchEffectPrefab, muzzleTransform.position, Quaternion.identity); + } + else + { + _emh_mulchEffect = EffectManager.GetAndActivatePooledEffect(mulchEffectPrefab, muzzleTransform.position, Quaternion.identity); + mulchEffect = _emh_mulchEffect.gameObject; + } + ChildLocator component = mulchEffect.gameObject.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("AreaIndicator"); + if ((bool)transform) + { + transform.localScale = new Vector3(maxTetherDistance * 2f, maxTetherDistance * 2f, maxTetherDistance * 2f); + } + } + mulchEffect.transform.parent = muzzleTransform; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/RecoverExit.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/RecoverExit.cs new file mode 100644 index 0000000..ea52d38 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/RecoverExit.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace EntityStates.ClayBoss; + +public class RecoverExit : BaseState +{ + public static float exitDuration = 1f; + + private float stopwatch; + + private static int ExitSiphonStateHash = Animator.StringToHash("ExitSiphon"); + + private static int ExitSiphonParamHash = Animator.StringToHash("ExitSiphon.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + PlayAnimation("Body", ExitSiphonStateHash, ExitSiphonParamHash, exitDuration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= exitDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/SpawnState.cs new file mode 100644 index 0000000..bc68419 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBoss/SpawnState.cs @@ -0,0 +1,49 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBoss; + +public class SpawnState : BaseState +{ + public static float duration; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + public static string spawnEffectChildString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(spawnEffectChildString); + if ((bool)transform) + { + Object.Instantiate(spawnEffectPrefab, transform.position, Quaternion.identity); + } + } + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/FireSonicBoom.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/FireSonicBoom.cs new file mode 100644 index 0000000..90d01ed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/FireSonicBoom.cs @@ -0,0 +1,30 @@ +using EntityStates.Treebot.Weapon; +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBruiser.Weapon; + +public class FireSonicBoom : EntityStates.Treebot.Weapon.FireSonicBoom +{ + private static int WeaponIsReadyParamHash = Animator.StringToHash("WeaponIsReady"); + + public override void OnEnter() + { + base.OnEnter(); + GetModelAnimator().SetBool(WeaponIsReadyParamHash, value: true); + } + + protected override void AddDebuff(CharacterBody body) + { + body.AddTimedBuff(RoR2Content.Buffs.ClayGoo, slowDuration); + } + + public override void OnExit() + { + if (!outer.destroying) + { + GetModelAnimator().SetBool(WeaponIsReadyParamHash, value: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunFire.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunFire.cs new file mode 100644 index 0000000..44c437d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunFire.cs @@ -0,0 +1,153 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBruiser.Weapon; + +public class MinigunFire : MinigunState +{ + public static GameObject muzzleVfxPrefab; + + public static float baseFireInterval; + + public static int baseBulletCount; + + public static float baseDamagePerSecondCoefficient; + + public static float baseForcePerSecond; + + public static float baseProcCoefficientPerSecond; + + public static float bulletMinSpread; + + public static float bulletMaxSpread; + + public static GameObject bulletTracerEffectPrefab; + + public static GameObject bulletHitEffectPrefab; + + public static bool bulletHitEffectNormal; + + public static float bulletMaxDistance; + + public static string fireSound; + + public static string startSound; + + public static string endSound; + + private float fireTimer; + + private Transform muzzleVfxTransform; + + private float baseFireRate; + + private float baseBulletsPerSecond; + + private Run.FixedTimeStamp critEndTime; + + private Run.FixedTimeStamp lastCritCheck; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)muzzleTransform && (bool)muzzleVfxPrefab) + { + muzzleVfxTransform = Object.Instantiate(muzzleVfxPrefab, muzzleTransform).transform; + } + baseFireRate = 1f / baseFireInterval; + baseBulletsPerSecond = (float)baseBulletCount * baseFireRate; + critEndTime = Run.FixedTimeStamp.negativeInfinity; + lastCritCheck = Run.FixedTimeStamp.negativeInfinity; + Util.PlaySound(startSound, base.gameObject); + PlayCrossfade("Gesture, Additive", "FireMinigun", 0.2f); + } + + private void UpdateCrits() + { + if (lastCritCheck.timeSince >= 1f) + { + lastCritCheck = Run.FixedTimeStamp.now; + if (RollCrit()) + { + critEndTime = Run.FixedTimeStamp.now + 2f; + } + } + } + + public override void OnExit() + { + Util.PlaySound(endSound, base.gameObject); + if ((bool)muzzleVfxTransform) + { + EntityState.Destroy(muzzleVfxTransform.gameObject); + muzzleVfxTransform = null; + } + PlayCrossfade("Gesture, Additive", "BufferEmpty", 0.2f); + base.OnExit(); + } + + private void OnFireShared() + { + Util.PlaySound(fireSound, base.gameObject); + if (base.isAuthority) + { + OnFireAuthority(); + } + } + + private void OnFireAuthority() + { + UpdateCrits(); + bool isCrit = !critEndTime.hasPassed; + float damage = baseDamagePerSecondCoefficient / baseBulletsPerSecond * damageStat; + float force = baseForcePerSecond / baseBulletsPerSecond; + float procCoefficient = baseProcCoefficientPerSecond / baseBulletsPerSecond; + Ray aimRay = GetAimRay(); + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.bulletCount = (uint)baseBulletCount; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.origin = aimRay.origin; + bulletAttack.damage = damage; + bulletAttack.damageColorIndex = DamageColorIndex.Default; + bulletAttack.damageType = DamageType.Generic; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.maxDistance = bulletMaxDistance; + bulletAttack.force = force; + bulletAttack.hitMask = LayerIndex.CommonMasks.bullet; + bulletAttack.minSpread = bulletMinSpread; + bulletAttack.maxSpread = bulletMaxSpread; + bulletAttack.isCrit = isCrit; + bulletAttack.owner = base.gameObject; + bulletAttack.muzzleName = MinigunState.muzzleName; + bulletAttack.smartCollision = false; + bulletAttack.procChainMask = default(ProcChainMask); + bulletAttack.procCoefficient = procCoefficient; + bulletAttack.radius = 0f; + bulletAttack.sniper = false; + bulletAttack.stopperMask = LayerIndex.CommonMasks.bullet; + bulletAttack.weapon = null; + bulletAttack.tracerEffectPrefab = bulletTracerEffectPrefab; + bulletAttack.spreadPitchScale = 1f; + bulletAttack.spreadYawScale = 1f; + bulletAttack.queryTriggerInteraction = QueryTriggerInteraction.UseGlobal; + bulletAttack.hitEffectPrefab = bulletHitEffectPrefab; + bulletAttack.HitEffectNormal = bulletHitEffectNormal; + bulletAttack.Fire(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + float num = baseFireInterval / attackSpeedStat; + fireTimer += num; + OnFireShared(); + } + if (base.isAuthority && !base.skillButtonState.down) + { + outer.SetNextState(new MinigunSpinDown()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunSpinDown.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunSpinDown.cs new file mode 100644 index 0000000..f622a8b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunSpinDown.cs @@ -0,0 +1,32 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBruiser.Weapon; + +public class MinigunSpinDown : MinigunState +{ + public static float baseDuration; + + public static string sound; + + private float duration; + + private static int WeaponIsReadyParamHash = Animator.StringToHash("WeaponIsReady"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(sound, base.gameObject, attackSpeedStat); + GetModelAnimator().SetBool(WeaponIsReadyParamHash, value: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunSpinUp.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunSpinUp.cs new file mode 100644 index 0000000..5e99410 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunSpinUp.cs @@ -0,0 +1,55 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBruiser.Weapon; + +public class MinigunSpinUp : MinigunState +{ + public static float baseDuration; + + public static string sound; + + public static GameObject chargeEffectPrefab; + + private GameObject chargeInstance; + + private float duration; + + private static int WeaponIsReadyParamHash = Animator.StringToHash("WeaponIsReady"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(sound, base.gameObject); + GetModelAnimator().SetBool(WeaponIsReadyParamHash, value: true); + if ((bool)muzzleTransform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + chargeInstance.transform.parent = muzzleTransform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new MinigunFire()); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunState.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunState.cs new file mode 100644 index 0000000..b06cfd0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiser.Weapon/MinigunState.cs @@ -0,0 +1,46 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ClayBruiser.Weapon; + +public class MinigunState : BaseState +{ + public static string muzzleName; + + private static readonly BuffDef slowBuff = RoR2Content.Buffs.Slow50; + + protected Transform muzzleTransform; + + protected ref InputBankTest.ButtonState skillButtonState => ref base.inputBank.skill1; + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.AddBuff(slowBuff); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + StartAimMode(); + } + + public override void OnExit() + { + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.RemoveBuff(slowBuff); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayBruiserMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiserMonster/SpawnState.cs new file mode 100644 index 0000000..27ab763 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayBruiserMonster/SpawnState.cs @@ -0,0 +1,56 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayBruiserMonster; + +public class SpawnState : BaseState +{ + public static float duration; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + public static string spawnEffectChildString; + + public static float startingPrintBias; + + public static float maxPrintBias; + + public static float printDuration; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnEffectChildString, transmit: false); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + PrintController printController = GetModelTransform().gameObject.AddComponent(); + printController.printTime = printDuration; + printController.enabled = true; + printController.startingPrintHeight = 0.3f; + printController.maxPrintHeight = 0.3f; + printController.startingPrintBias = startingPrintBias; + printController.maxPrintBias = maxPrintBias; + printController.disableWhenFinished = true; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/FaceSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/FaceSlam.cs new file mode 100644 index 0000000..55bbcab --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/FaceSlam.cs @@ -0,0 +1,184 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ClayGrenadier; + +public class FaceSlam : BaseState +{ + public static float baseDuration = 3.5f; + + public static float baseDurationBeforeBlast = 1.5f; + + public static string animationLayerName = "Body"; + + public static string animationStateName = "FaceSlam"; + + public static string playbackRateParam = "FaceSlam.playbackRate"; + + private static int FaceSlamStateHash = Animator.StringToHash("FaceSlam"); + + private static int FaceSlamParamHash = Animator.StringToHash("FaceSlam.playbackRate"); + + public static GameObject chargeEffectPrefab; + + public static string chargeEffectMuzzleString; + + public static GameObject blastImpactEffect; + + public static float blastDamageCoefficient = 4f; + + public static float blastForceMagnitude = 16f; + + public static float blastUpwardForce; + + public static float blastRadius = 3f; + + public static string attackSoundString; + + public static string blastMuzzleString; + + public static GameObject projectilePrefab; + + public static float projectileDamageCoefficient; + + public static float projectileForce; + + public static float projectileSnapOnAngle; + + public static float healthCostFraction; + + private BlastAttack attack; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasFiredBlast; + + private float duration; + + private float durationBeforeBlast; + + private GameObject chargeInstance; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + duration = baseDuration / attackSpeedStat; + durationBeforeBlast = baseDurationBeforeBlast / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayAnimation(animationLayerName, FaceSlamStateHash, FaceSlamParamHash, duration); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + Transform transform = FindModelChild(chargeEffectMuzzleString); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = durationBeforeBlast; + } + } + } + + public override void OnExit() + { + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > durationBeforeBlast && !hasFiredBlast) + { + hasFiredBlast = true; + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + Vector3 footPosition = base.characterBody.footPosition; + EffectManager.SpawnEffect(blastImpactEffect, new EffectData + { + origin = footPosition, + scale = blastRadius + }, transmit: true); + if (NetworkServer.active && (bool)base.healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal | DamageType.BypassArmor; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + if (base.isAuthority) + { + if ((bool)modelTransform) + { + Transform transform = FindModelChild(blastMuzzleString); + if ((bool)transform) + { + attack = new BlastAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * blastDamageCoefficient; + attack.baseForce = blastForceMagnitude; + attack.position = transform.position; + attack.radius = blastRadius; + attack.bonusForce = new Vector3(0f, blastUpwardForce, 0f); + attack.damageType = DamageType.ClayGoo; + attack.Fire(); + } + } + Vector3 position = footPosition; + _ = Vector3.up; + if (Physics.Raycast(GetAimRay(), out var hitInfo, 1000f, LayerIndex.world.mask)) + { + position = hitInfo.point; + } + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(base.characterBody.teamComponent.teamIndex); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.minDistanceFilter = 0f; + bullseyeSearch.maxDistanceFilter = 1000f; + bullseyeSearch.searchOrigin = base.inputBank.aimOrigin; + bullseyeSearch.searchDirection = base.inputBank.aimDirection; + bullseyeSearch.maxAngleFilter = projectileSnapOnAngle; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)hurtBox && (bool)hurtBox.healthComponent) + { + position = hurtBox.healthComponent.body.footPosition; + } + ProjectileManager.instance.FireProjectile(projectilePrefab, position, Quaternion.identity, base.gameObject, base.characterBody.damage * projectileDamageCoefficient, projectileForce, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/SpawnState.cs new file mode 100644 index 0000000..d36cff5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/SpawnState.cs @@ -0,0 +1,74 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClayGrenadier; + +public class SpawnState : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string spawnSoundString; + + [SerializeField] + public GameObject spawnEffectPrefab; + + [SerializeField] + public string spawnEffectChildString; + + [SerializeField] + public float startingPrintBias; + + [SerializeField] + public float maxPrintBias; + + [SerializeField] + public float printDuration; + + [SerializeField] + public float startingPrintHeight = 0.3f; + + [SerializeField] + public float maxPrintHeight = 0.3f; + + [SerializeField] + public string animationLayerName = "Body"; + + [SerializeField] + public string animationStateName = "Spawn"; + + [SerializeField] + public string playbackRateParam = "Spawn.playbackRate"; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnEffectChildString, transmit: false); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, duration); + PrintController printController = GetModelTransform().gameObject.AddComponent(); + printController.printTime = printDuration; + printController.enabled = true; + printController.startingPrintHeight = startingPrintHeight; + printController.maxPrintHeight = maxPrintHeight; + printController.startingPrintBias = startingPrintBias; + printController.maxPrintBias = maxPrintBias; + printController.disableWhenFinished = true; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/ThrowBarrel.cs b/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/ThrowBarrel.cs new file mode 100644 index 0000000..000a544 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClayGrenadier/ThrowBarrel.cs @@ -0,0 +1,113 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ClayGrenadier; + +public class ThrowBarrel : GenericProjectileBaseState +{ + [SerializeField] + public float aimCalculationRaycastDistance; + + [SerializeField] + public string animationLayerName = "Body"; + + [SerializeField] + public string animationStateName = "FaceSlam"; + + [SerializeField] + public string playbackRateParam = "FaceSlam.playbackRate"; + + [SerializeField] + public int projectileCount; + + [SerializeField] + public float projectilePitchBonusPerProjectile; + + [SerializeField] + public float projectileYawBonusPerProjectile; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string chargeEffectMuzzleString; + + [SerializeField] + public string enterSoundString; + + private GameObject chargeInstance; + + private int currentProjectileCount; + + protected override void PlayAnimation(float duration) + { + base.PlayAnimation(duration); + PlayCrossfade(animationLayerName, animationStateName, playbackRateParam, duration, 0.2f); + } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + base.characterBody.SetAimTimer(0f); + Transform transform = FindModelChild(chargeEffectMuzzleString); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = delayBeforeFiringProjectile; + } + } + } + + protected override Ray ModifyProjectileAimRay(Ray aimRay) + { + RaycastHit hitInfo = default(RaycastHit); + Ray ray = aimRay; + float desiredForwardSpeed = projectilePrefab.GetComponent().desiredForwardSpeed; + ray.origin = aimRay.origin; + if (Util.CharacterRaycast(base.gameObject, ray, out hitInfo, float.PositiveInfinity, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + float num = desiredForwardSpeed; + Vector3 vector = hitInfo.point - aimRay.origin; + Vector2 vector2 = new Vector2(vector.x, vector.z); + float magnitude = vector2.magnitude; + float y = Trajectory.CalculateInitialYSpeed(magnitude / num, vector.y); + Vector3 vector3 = new Vector3(vector2.x / magnitude * num, y, vector2.y / magnitude * num); + desiredForwardSpeed = vector3.magnitude; + aimRay.direction = vector3 / desiredForwardSpeed; + } + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, 0f, 1f, 1f, projectileYawBonusPerProjectile * (float)currentProjectileCount, projectilePitchBonusPerProjectile * (float)currentProjectileCount); + return aimRay; + } + + protected override void FireProjectile() + { + for (int i = 0; i < projectileCount; i++) + { + base.FireProjectile(); + currentProjectileCount++; + } + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + } + + public override void OnExit() + { + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/Leap.cs b/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/Leap.cs new file mode 100644 index 0000000..ae77755 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/Leap.cs @@ -0,0 +1,73 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClaymanMonster; + +public class Leap : BaseState +{ + public static string leapSoundString; + + public static float minimumDuration; + + public static float verticalJumpSpeed; + + public static float horizontalJumpSpeedCoefficient; + + private Vector3 forwardDirection; + + private Animator animator; + + private float stopwatch; + + private bool playedImpact; + + private static int LeapcycleParamHash = Animator.StringToHash("Leap.cycle"); + + private static int LightImpactStateHash = Animator.StringToHash("LightImpact"); + + private static int IdleStateHash = Animator.StringToHash("Idle"); + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + Util.PlaySound(leapSoundString, base.gameObject); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity.y = verticalJumpSpeed; + } + forwardDirection = Vector3.ProjectOnPlane(base.inputBank.aimDirection, Vector3.up); + base.characterDirection.moveVector = forwardDirection; + PlayCrossfade("Body", "LeapAirLoop", 0.15f); + } + + public override void FixedUpdate() + { + stopwatch += GetDeltaTime(); + animator.SetFloat(LeapcycleParamHash, Mathf.Clamp01(Util.Remap(base.characterMotor.velocity.y, 0f - verticalJumpSpeed, verticalJumpSpeed, 1f, 0f))); + Vector3 velocity = forwardDirection * base.characterBody.moveSpeed * horizontalJumpSpeedCoefficient; + velocity.y = base.characterMotor.velocity.y; + base.characterMotor.velocity = velocity; + base.FixedUpdate(); + if (base.characterMotor.isGrounded && stopwatch > minimumDuration && !playedImpact) + { + playedImpact = true; + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 1.5f); + animator.PlayInFixedTime(LightImpactStateHash, layerIndex, 0f); + } + if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + PlayAnimation("Body", IdleStateHash); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/SpawnState.cs new file mode 100644 index 0000000..9651d09 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/SpawnState.cs @@ -0,0 +1,52 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ClaymanMonster; + +public class SpawnState : BaseState +{ + public static float duration; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + public static string spawnEffectChildString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(spawnEffectChildString); + if ((bool)transform) + { + Object.Instantiate(spawnEffectPrefab, transform.position, Quaternion.identity); + } + } + if (spawnSoundString.Length > 0) + { + Util.PlaySound(spawnSoundString, base.gameObject); + } + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/SwipeForward.cs b/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/SwipeForward.cs new file mode 100644 index 0000000..f42ca63 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ClaymanMonster/SwipeForward.cs @@ -0,0 +1,98 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ClaymanMonster; + +public class SwipeForward : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float selfForceMagnitude; + + public static float radius = 3f; + + public static GameObject hitEffectPrefab; + + public static GameObject swingEffectPrefab; + + public static string attackString; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private bool hasSlashed; + + private static int SwipeForwardStateHash = Animator.StringToHash("SwipeForward"); + + private static int SwipeForwardParamHash = Animator.StringToHash("SwipeForward.playbackRate"); + + private static int SwipeForwardHitboxActiveParamHash = Animator.StringToHash("SwipeForward.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + Util.PlaySound(attackString, base.gameObject); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Sword"); + } + if ((bool)modelAnimator) + { + PlayAnimation("Gesture, Override", SwipeForwardStateHash, SwipeForwardParamHash, duration); + PlayAnimation("Gesture, Additive", SwipeForwardStateHash, SwipeForwardParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat(SwipeForwardHitboxActiveParamHash) > 0.1f) + { + if (!hasSlashed) + { + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, "SwingCenter", transmit: true); + HealthComponent healthComponent = base.characterBody.healthComponent; + CharacterDirection component = base.characterBody.GetComponent(); + if ((bool)healthComponent) + { + healthComponent.TakeDamageForce(selfForceMagnitude * component.forward, alwaysApply: true); + } + hasSlashed = true; + } + attack.forceVector = base.transform.forward * forceMagnitude; + attack.Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/CastSmokescreen.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/CastSmokescreen.cs new file mode 100644 index 0000000..2398755 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/CastSmokescreen.cs @@ -0,0 +1,138 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Commando.CommandoWeapon; + +public class CastSmokescreen : BaseState +{ + public static float baseDuration; + + public static float stealthDuration = 3f; + + public static string jumpSoundString; + + public static string startCloakSoundString; + + public static string stopCloakSoundString; + + public static GameObject initialEffectPrefab; + + public static GameObject smokescreenEffectPrefab; + + public static float damageCoefficient = 1.3f; + + public static float radius = 4f; + + public static float forceMagnitude = 100f; + + private float duration; + + private float totalDuration; + + private bool hasCastSmoke; + + private Animator animator; + + private void CastSmoke() + { + if (!hasCastSmoke) + { + Util.PlaySound(startCloakSoundString, base.gameObject); + } + else + { + Util.PlaySound(stopCloakSoundString, base.gameObject); + } + EffectManager.SpawnEffect(smokescreenEffectPrefab, new EffectData + { + origin = base.transform.position + }, transmit: false); + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 2f); + animator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = forceMagnitude; + blastAttack.position = base.transform.position; + blastAttack.radius = radius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.damageType = DamageType.Stun1s; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + } + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + totalDuration = stealthDuration + totalDuration; + PlayCrossfade("Gesture, Smokescreen", "CastSmokescreen", "CastSmokescreen.playbackRate", duration, 0.2f); + animator = GetModelAnimator(); + Util.PlaySound(jumpSoundString, base.gameObject); + EffectManager.SpawnEffect(initialEffectPrefab, new EffectData + { + origin = base.transform.position + }, transmit: true); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.CloakSpeed.buffIndex); + } + } + + public override void OnExit() + { + if ((bool)base.characterBody && NetworkServer.active) + { + if (base.characterBody.HasBuff(RoR2Content.Buffs.Cloak)) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Cloak); + } + if (base.characterBody.HasBuff(RoR2Content.Buffs.CloakSpeed)) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.CloakSpeed); + } + } + if (!outer.destroying) + { + CastSmoke(); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && !hasCastSmoke) + { + CastSmoke(); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Cloak.buffIndex); + } + hasCastSmoke = true; + } + if (base.fixedAge >= totalDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!hasCastSmoke) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/CastSmokescreenNoDelay.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/CastSmokescreenNoDelay.cs new file mode 100644 index 0000000..72ca35c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/CastSmokescreenNoDelay.cs @@ -0,0 +1,131 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Commando.CommandoWeapon; + +public class CastSmokescreenNoDelay : BaseState +{ + public static float duration; + + public static float minimumStateDuration = 3f; + + public static string startCloakSoundString; + + public static string stopCloakSoundString; + + public static GameObject smokescreenEffectPrefab; + + public static Material destealthMaterial; + + public static float damageCoefficient = 1.3f; + + public static float radius = 4f; + + public static float forceMagnitude = 100f; + + private float stopwatch; + + private bool hasCastSmoke; + + private Animator animator; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + CastSmoke(); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Cloak); + base.characterBody.AddBuff(RoR2Content.Buffs.CloakSpeed); + } + } + + public override void OnExit() + { + if ((bool)base.characterBody && NetworkServer.active) + { + if (base.characterBody.HasBuff(RoR2Content.Buffs.Cloak)) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Cloak); + } + if (base.characterBody.HasBuff(RoR2Content.Buffs.CloakSpeed)) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.CloakSpeed); + } + } + if (!outer.destroying) + { + CastSmoke(); + } + if ((bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(animator.gameObject); + temporaryOverlayInstance.duration = 1f; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = animator.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void CastSmoke() + { + if (!hasCastSmoke) + { + Util.PlaySound(startCloakSoundString, base.gameObject); + hasCastSmoke = true; + } + else + { + Util.PlaySound(stopCloakSoundString, base.gameObject); + } + EffectManager.SpawnEffect(smokescreenEffectPrefab, new EffectData + { + origin = base.transform.position + }, transmit: false); + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 1f); + animator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = forceMagnitude; + blastAttack.position = base.transform.position; + blastAttack.radius = radius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.damageType = DamageType.Stun1s; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(stopwatch > minimumStateDuration)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireBarrage.cs new file mode 100644 index 0000000..03f6319 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireBarrage.cs @@ -0,0 +1,137 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireBarrage : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static float baseDurationBetweenShots = 1f; + + public static float totalDuration = 2f; + + public static float bulletRadius = 1.5f; + + public static int baseBulletCount = 1; + + public static string fireBarrageSoundString; + + public static float recoilAmplitude; + + public static float spreadBloomValue; + + private int totalBulletsFired; + + private int bulletCount; + + public float stopwatchBetweenShots; + + private Animator modelAnimator; + + private Transform modelTransform; + + private float duration; + + private float durationBetweenShots; + + private static int FireBarrageStateHash = Animator.StringToHash("FireBarrage"); + + private static int FireBarrageParamHash = Animator.StringToHash("FireBarrage.playbackRate"); + + private static int FirePistolRightStateHash = Animator.StringToHash("FirePistol, Right"); + + public override void OnEnter() + { + base.OnEnter(); + base.characterBody.SetSpreadBloom(0.2f, canOnlyIncreaseBloom: false); + duration = totalDuration; + durationBetweenShots = baseDurationBetweenShots / attackSpeedStat; + bulletCount = (int)((float)baseBulletCount * attackSpeedStat); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + PlayCrossfade("Gesture, Additive", FireBarrageStateHash, FireBarrageParamHash, duration, 0.2f); + PlayCrossfade("Gesture, Override", FireBarrageStateHash, FireBarrageParamHash, duration, 0.2f); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + FireBullet(); + } + + private void FireBullet() + { + Ray aimRay = GetAimRay(); + string muzzleName = "MuzzleRight"; + if ((bool)modelAnimator) + { + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + PlayAnimation("Gesture Additive, Right", FirePistolRightStateHash); + } + AddRecoil(-0.8f * recoilAmplitude, -1f * recoilAmplitude, -0.1f * recoilAmplitude, 0.15f * recoilAmplitude); + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.radius = bulletRadius; + bulletAttack.smartCollision = true; + bulletAttack.damageType = DamageType.Stun1s; + bulletAttack.Fire(); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + totalBulletsFired++; + Util.PlaySound(fireBarrageSoundString, base.gameObject); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatchBetweenShots += GetDeltaTime(); + if (stopwatchBetweenShots >= durationBetweenShots && totalBulletsFired < bulletCount) + { + stopwatchBetweenShots -= durationBetweenShots; + FireBullet(); + } + if (base.fixedAge >= duration && totalBulletsFired == bulletCount && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireFMJ.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireFMJ.cs new file mode 100644 index 0000000..3cf1498 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireFMJ.cs @@ -0,0 +1,27 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireFMJ : GenericProjectileBaseState +{ + private static int FireFMJStateHash = Animator.StringToHash("FireFMJ"); + + private static int FireFMJParamHash = Animator.StringToHash("FireFMJ.playbackRate"); + + protected override void PlayAnimation(float duration) + { + base.PlayAnimation(duration); + if ((bool)GetModelAnimator()) + { + PlayAnimation("Gesture, Additive", FireFMJStateHash, FireFMJParamHash, duration); + PlayAnimation("Gesture, Override", FireFMJStateHash, FireFMJParamHash, duration); + } + } + + protected override Ray ModifyProjectileAimRay(Ray aimRay) + { + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref aimRay, projectilePrefab, base.gameObject); + return aimRay; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireLightsOut.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireLightsOut.cs new file mode 100644 index 0000000..6c1e784 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireLightsOut.cs @@ -0,0 +1,98 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireLightsOut : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public static float recoilAmplitude; + + private ChildLocator childLocator; + + public int bulletCountCurrent = 1; + + private float duration; + + private static int FireRevolverStateHash = Animator.StringToHash("FireRevolver"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + AddRecoil(-3f * recoilAmplitude, -4f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "MuzzlePistol"; + Util.PlaySound(attackSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", FireRevolverStateHash); + PlayAnimation("Gesture, Override", FireRevolverStateHash); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + BulletAttack obj = new BulletAttack + { + owner = base.gameObject, + weapon = base.gameObject, + origin = aimRay.origin, + aimVector = aimRay.direction, + minSpread = minSpread, + maxSpread = maxSpread, + bulletCount = ((bulletCount > 0) ? ((uint)bulletCount) : 0u), + damage = damageCoefficient * damageStat, + force = force, + falloffModel = BulletAttack.FalloffModel.None, + tracerEffectPrefab = tracerEffectPrefab, + muzzleName = muzzleName, + hitEffectPrefab = hitEffectPrefab, + isCrit = Util.CheckRoll(critStat, base.characterBody.master), + HitEffectNormal = false, + radius = 0.5f + }; + obj.damageType |= (DamageTypeCombo)DamageType.ResetCooldownsOnKill; + obj.smartCollision = true; + obj.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FirePistol2.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FirePistol2.cs new file mode 100644 index 0000000..16eedb0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FirePistol2.cs @@ -0,0 +1,115 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FirePistol2 : BaseSkillState, SteppedSkillDef.IStepSetter +{ + public static GameObject muzzleEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float baseDuration = 2f; + + public static string firePistolSoundString; + + public static float recoilAmplitude = 1f; + + public static float spreadBloomValue = 0.3f; + + public static float commandoBoostBuffCoefficient = 0.4f; + + public static float trajectoryAimAssistMultiplier = 0.75f; + + private int pistol; + + private Ray aimRay; + + private float duration; + + private static int FirePistolLeftStateHash = Animator.StringToHash("FirePistol, Left"); + + private static int FirePistolRightStateHash = Animator.StringToHash("FirePistol, Right"); + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + pistol = i; + } + + private void FireBullet(string targetMuzzle) + { + Util.PlaySound(firePistolSoundString, base.gameObject); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + AddRecoil(-0.4f * recoilAmplitude, -0.8f * recoilAmplitude, -0.3f * recoilAmplitude, 0.3f * recoilAmplitude); + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.radius = 0.1f; + bulletAttack.smartCollision = true; + bulletAttack.trajectoryAimAssistMultiplier = trajectoryAimAssistMultiplier; + bulletAttack.Fire(); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + aimRay = GetAimRay(); + StartAimMode(aimRay, 3f); + if (pistol % 2 == 0) + { + PlayAnimation("Gesture Additive, Left", FirePistolLeftStateHash); + FireBullet("MuzzleLeft"); + } + else + { + PlayAnimation("Gesture Additive, Right", FirePistolRightStateHash); + FireBullet("MuzzleRight"); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + if (base.activatorSkillSlot.stock <= 0) + { + outer.SetNextState(new ReloadPistols()); + } + else + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireRocket.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireRocket.cs new file mode 100644 index 0000000..ee0154b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireRocket.cs @@ -0,0 +1,63 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireRocket : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float baseDuration = 2f; + + private float duration; + + public int bulletCountCurrent = 1; + + private static int FireFMJStateHash = Animator.StringToHash("FireFMJ"); + + private static int FireFMJParamHash = Animator.StringToHash("FireFMJ.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "MuzzleCenter"; + PlayAnimation("Gesture", FireFMJStateHash, FireFMJParamHash, duration); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShotgun.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShotgun.cs new file mode 100644 index 0000000..062470c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShotgun.cs @@ -0,0 +1,104 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireShotgun : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static int bulletCount; + + public static float baseMaxDuration = 2f; + + public static float baseMinDuration = 0.5f; + + public static string attackSoundString; + + public static float recoilAmplitude; + + public static float spreadBloomValue = 0.3f; + + private float maxDuration; + + private float minDuration; + + private static int FireShotgunStateHash = Animator.StringToHash("FireShotgun"); + + private static int FireShotgunParamHash = Animator.StringToHash("FireShotgun.playbackRate"); + + private bool buttonReleased; + + public override void OnEnter() + { + base.OnEnter(); + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + maxDuration = baseMaxDuration / attackSpeedStat; + minDuration = baseMinDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + Util.PlaySound(attackSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", FireShotgunStateHash, FireShotgunParamHash, maxDuration * 1.1f); + PlayAnimation("Gesture, Override", FireShotgunStateHash, FireShotgunParamHash, maxDuration * 1.1f); + string muzzleName = "MuzzleShotgun"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.bulletCount = ((bulletCount > 0) ? ((uint)bulletCount) : 0u); + bulletAttack.procCoefficient = 1f / (float)bulletCount; + bulletAttack.damage = damageCoefficient * damageStat / (float)bulletCount; + bulletAttack.force = force; + bulletAttack.falloffModel = BulletAttack.FalloffModel.DefaultBullet; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0f; + bulletAttack.Fire(); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + buttonReleased |= !base.inputBank.skill1.down; + if (base.fixedAge >= maxDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (buttonReleased && base.fixedAge >= minDuration) + { + return InterruptPriority.Any; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShotgunBlast.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShotgunBlast.cs new file mode 100644 index 0000000..4a0bd21 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShotgunBlast.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireShotgunBlast : GenericBulletBaseState +{ + public static float delayBetweenShotgunBlasts; + + private bool hasFiredSecondBlast; + + private static int FirePistolLeftStateHash = Animator.StringToHash("FirePistol, Left"); + + private static int FirePistolRightStateHash = Animator.StringToHash("FirePistol, Right"); + + public override void OnEnter() + { + muzzleName = "MuzzleLeft"; + base.OnEnter(); + PlayAnimation("Gesture Additive, Left", FirePistolLeftStateHash); + PlayAnimation("Gesture Override, Left", FirePistolLeftStateHash); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!hasFiredSecondBlast && delayBetweenShotgunBlasts / attackSpeedStat < base.fixedAge) + { + hasFiredSecondBlast = true; + PlayAnimation("Gesture Additive, Right", FirePistolRightStateHash); + PlayAnimation("Gesture Override, Right", FirePistolRightStateHash); + muzzleName = "MuzzleRight"; + FireBullet(GetAimRay()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShrapnel.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShrapnel.cs new file mode 100644 index 0000000..d72cacb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireShrapnel.cs @@ -0,0 +1,108 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireShrapnel : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float blastRadius; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public static float maxDistance; + + private float duration; + + private Ray modifiedAimRay; + + private static int FireLaserStateHash = Animator.StringToHash("FireLaser"); + + private static int FireLaserParamHash = Animator.StringToHash("FireLaser.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modifiedAimRay = GetAimRay(); + Util.PlaySound(attackSoundString, base.gameObject); + string muzzleName = "MuzzleLaser"; + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + PlayAnimation("Gesture", FireLaserStateHash, FireLaserParamHash, duration); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + if (Physics.Raycast(modifiedAimRay, out var hitInfo, 1000f, (int)LayerIndex.world.mask | (int)LayerIndex.CommonMasks.characterBodiesOrDefault)) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = force * 0.2f; + blastAttack.position = hitInfo.point; + blastAttack.radius = blastRadius; + blastAttack.Fire(); + } + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = modifiedAimRay.origin; + bulletAttack.aimVector = modifiedAimRay.direction; + bulletAttack.radius = 0.25f; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = ((bulletCount > 0) ? ((uint)bulletCount) : 0u); + bulletAttack.damage = 0f; + bulletAttack.procCoefficient = 0f; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireSweepBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireSweepBarrage.cs new file mode 100644 index 0000000..97bb312 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireSweepBarrage.cs @@ -0,0 +1,168 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireSweepBarrage : BaseState +{ + public static string enterSound; + + public static string muzzle; + + public static string fireSoundString; + + public static GameObject muzzleEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float baseTotalDuration; + + public static float baseFiringDuration; + + public static float fieldOfView; + + public static float maxDistance; + + public static float damageCoefficient; + + public static float procCoefficient; + + public static float force; + + public static int minimumFireCount; + + public static GameObject impactEffectPrefab; + + private float totalDuration; + + private float firingDuration; + + private int totalBulletsToFire; + + private int totalBulletsFired; + + private int targetHurtboxIndex; + + private float timeBetweenBullets; + + private List targetHurtboxes = new List(); + + private float fireTimer; + + private ChildLocator childLocator; + + private int muzzleIndex; + + private Transform muzzleTransform; + + private static int FireSweepBarrageStateHash = Animator.StringToHash("FireSweepBarrage"); + + private static int FireSweepBarrageParamHash = Animator.StringToHash("FireSweepBarrage.playbackRate"); + + private static int FirePistolRightStateHash = Animator.StringToHash("FirePistol, Right"); + + public override void OnEnter() + { + base.OnEnter(); + totalDuration = baseTotalDuration / attackSpeedStat; + firingDuration = baseFiringDuration / attackSpeedStat; + base.characterBody.SetAimTimer(3f); + PlayAnimation("Gesture, Additive", FireSweepBarrageStateHash, FireSweepBarrageParamHash, totalDuration); + PlayAnimation("Gesture, Override", FireSweepBarrageStateHash, FireSweepBarrageParamHash, totalDuration); + Util.PlaySound(enterSound, base.gameObject); + Ray aimRay = GetAimRay(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); + bullseyeSearch.maxAngleFilter = fieldOfView * 0.5f; + bullseyeSearch.maxDistanceFilter = maxDistance; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.filterByLoS = true; + bullseyeSearch.RefreshCandidates(); + targetHurtboxes = bullseyeSearch.GetResults().Where(Util.IsValid).Distinct(default(HurtBox.EntityEqualityComparer)) + .ToList(); + totalBulletsToFire = Mathf.Max(targetHurtboxes.Count, minimumFireCount); + timeBetweenBullets = firingDuration / (float)totalBulletsToFire; + childLocator = GetModelTransform().GetComponent(); + muzzleIndex = childLocator.FindChildIndex(muzzle); + muzzleTransform = childLocator.FindChild(muzzleIndex); + } + + private void Fire() + { + if (totalBulletsFired >= totalBulletsToFire) + { + return; + } + if (!string.IsNullOrEmpty(muzzle)) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzle, transmit: false); + } + Util.PlaySound(fireSoundString, base.gameObject); + PlayAnimation("Gesture Additive, Right", FirePistolRightStateHash); + if (NetworkServer.active && targetHurtboxes.Count > 0) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageStat * damageCoefficient; + damageInfo.attacker = base.gameObject; + damageInfo.procCoefficient = procCoefficient; + damageInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + if (targetHurtboxIndex >= targetHurtboxes.Count) + { + targetHurtboxIndex = 0; + } + HurtBox hurtBox = targetHurtboxes[targetHurtboxIndex]; + if ((bool)hurtBox) + { + HealthComponent healthComponent = hurtBox.healthComponent; + if ((bool)healthComponent) + { + targetHurtboxIndex++; + Vector3 normalized = (hurtBox.transform.position - base.characterBody.corePosition).normalized; + damageInfo.force = force * normalized; + damageInfo.position = hurtBox.transform.position; + EffectManager.SimpleImpactEffect(impactEffectPrefab, hurtBox.transform.position, normalized, transmit: true); + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + } + if ((bool)tracerEffectPrefab && (bool)childLocator) + { + int childIndex = childLocator.FindChildIndex(muzzle); + childLocator.FindChild(childIndex); + EffectData effectData = new EffectData + { + origin = hurtBox.transform.position, + start = muzzleTransform.position + }; + effectData.SetChildLocatorTransformReference(base.gameObject, childIndex); + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + } + } + } + totalBulletsFired++; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + Fire(); + fireTimer += timeBetweenBullets; + } + if (base.fixedAge >= totalDuration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireThermite.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireThermite.cs new file mode 100644 index 0000000..2001cd6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/FireThermite.cs @@ -0,0 +1,71 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class FireThermite : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient; + + public static float force; + + public static float selfForce; + + public static float baseDuration = 2f; + + private float duration; + + public int bulletCountCurrent = 1; + + private static int FireFMJStateHash = Animator.StringToHash("FireFMJ"); + + private static int FireFMJParamHash = Animator.StringToHash("FireFMJ.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + PlayAnimation("Gesture", FireFMJStateHash, FireFMJParamHash, duration); + string muzzleName = "MuzzleCenter"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + if ((bool)base.characterMotor && !base.characterMotor.isGrounded) + { + Vector3 vector = -aimRay.direction * selfForce; + vector.y *= 0.5f; + base.characterMotor.ApplyForce(vector, alwaysApply: true); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/PrepBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/PrepBarrage.cs new file mode 100644 index 0000000..e051a77 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/PrepBarrage.cs @@ -0,0 +1,50 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class PrepBarrage : BaseState +{ + public static float baseDuration = 3f; + + public static string prepBarrageSoundString; + + private float duration; + + private Animator modelAnimator; + + private static int PrepBarrageStateHash = Animator.StringToHash("PrepBarrage"); + + private static int PrepBarrageParamHash = Animator.StringToHash("PrepBarrage.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", PrepBarrageStateHash, PrepBarrageParamHash, duration); + } + Util.PlaySound(prepBarrageSoundString, base.gameObject); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireBarrage nextState = new FireBarrage(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/PrepLightsOut.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/PrepLightsOut.cs new file mode 100644 index 0000000..2da554a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/PrepLightsOut.cs @@ -0,0 +1,112 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class PrepLightsOut : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargePrefab; + + public static GameObject specialCrosshairPrefab; + + public static string prepSoundString; + + private GameObject chargeEffect; + + private float duration; + + private ChildLocator childLocator; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private EffectManagerHelper _emh_chargeEffect; + + private static int PrepRevolverStateHash = Animator.StringToHash("PrepRevolver"); + + private static int PrepRevolverParamHash = Animator.StringToHash("PrepRevolver.playbackRate"); + + public override void Reset() + { + base.Reset(); + chargeEffect = null; + duration = 0f; + childLocator = null; + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", PrepRevolverStateHash, PrepRevolverParamHash, duration); + PlayAnimation("Gesture, Override", PrepRevolverStateHash, PrepRevolverParamHash, duration); + Util.PlaySound(prepSoundString, base.gameObject); + if ((bool)specialCrosshairPrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, specialCrosshairPrefab, CrosshairUtils.OverridePriority.Skill); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild("MuzzlePistol"); + if ((bool)transform && (bool)chargePrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargePrefab)) + { + chargeEffect = Object.Instantiate(chargePrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(chargePrefab, transform.position, transform.rotation); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffect.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new FireLightsOut()); + } + } + + public override void OnExit() + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + chargeEffect = null; + _emh_chargeEffect = null; + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ReloadPistols.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ReloadPistols.cs new file mode 100644 index 0000000..56ba1bf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ReloadPistols.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class ReloadPistols : GenericReload +{ + private static int ReloadPistolsStateHash = Animator.StringToHash("ReloadPistols"); + + private static int ReloadPistolsParamHash = Animator.StringToHash("ReloadPistols.playbackRate"); + + private static int ReloadPistolsExitStateHash = Animator.StringToHash("ReloadPistolsExit"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Gesture, Override", ReloadPistolsStateHash, ReloadPistolsParamHash, duration); + PlayAnimation("Gesture, Additive", ReloadPistolsStateHash, ReloadPistolsParamHash, duration); + FindModelChild("GunMeshL")?.gameObject.SetActive(value: false); + FindModelChild("GunMeshR")?.gameObject.SetActive(value: false); + } + + public override void OnExit() + { + FindModelChild("ReloadFXL")?.gameObject.SetActive(value: false); + FindModelChild("ReloadFXR")?.gameObject.SetActive(value: false); + FindModelChild("GunMeshL")?.gameObject.SetActive(value: true); + FindModelChild("GunMeshR")?.gameObject.SetActive(value: true); + PlayAnimation("Gesture, Override", ReloadPistolsExitStateHash); + PlayAnimation("Gesture, Additive", ReloadPistolsExitStateHash); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ThrowGrenade.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ThrowGrenade.cs new file mode 100644 index 0000000..13eaad5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ThrowGrenade.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +namespace EntityStates.Commando.CommandoWeapon; + +public class ThrowGrenade : GenericProjectileBaseState +{ + private static int ThrowGrenadeStateHash = Animator.StringToHash("ThrowGrenade"); + + private static int FireFMJParamHash = Animator.StringToHash("FireFMJ.playbackRate"); + + protected override void PlayAnimation(float duration) + { + if ((bool)GetModelAnimator()) + { + PlayAnimation("Gesture, Additive", ThrowGrenadeStateHash, FireFMJParamHash, duration * 2f); + PlayAnimation("Gesture, Override", ThrowGrenadeStateHash, FireFMJParamHash, duration * 2f); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ThrowStickyGrenade.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ThrowStickyGrenade.cs new file mode 100644 index 0000000..0fd375d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando.CommandoWeapon/ThrowStickyGrenade.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Commando.CommandoWeapon; + +public class ThrowStickyGrenade : ThrowGrenade +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando/CombatDodge.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando/CombatDodge.cs new file mode 100644 index 0000000..cbd6a88 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando/CombatDodge.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando; + +public class CombatDodge : DodgeState +{ + public static float durationToFire; + + public static int bulletCount; + + public static GameObject muzzleEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static string firePistolSoundString; + + public static float recoilAmplitude = 1f; + + public static float range; + + private int bulletsFired; + + private BullseyeSearch search; + + private static int FirePistolLeftStateHash = Animator.StringToHash("FirePistol, Left"); + + private static int FirePistolRightStateHash = Animator.StringToHash("FirePistol, Right"); + + public override void OnEnter() + { + base.OnEnter(); + search = new BullseyeSearch(); + search.searchDirection = Vector3.zero; + search.teamMaskFilter = TeamMask.allButNeutral; + search.teamMaskFilter.RemoveTeam(base.characterBody.teamComponent.teamIndex); + search.filterByLoS = true; + search.sortMode = BullseyeSearch.SortMode.Distance; + search.maxDistanceFilter = range; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float num = base.fixedAge / durationToFire; + if (bulletsFired < bulletCount && num > (float)bulletsFired / (float)bulletCount) + { + if (bulletsFired % 2 == 0) + { + PlayAnimation("Gesture Additive, Left", FirePistolLeftStateHash); + FireBullet("MuzzleLeft"); + } + else + { + PlayAnimation("Gesture Additive, Right", FirePistolRightStateHash); + FireBullet("MuzzleRight"); + } + } + } + + private HurtBox PickNextTarget() + { + search.searchOrigin = GetAimRay().origin; + search.RefreshCandidates(); + List list = search.GetResults().ToList(); + if (list.Count <= 0) + { + return null; + } + return list[Random.Range(0, list.Count)]; + } + + private void FireBullet(string targetMuzzle) + { + bulletsFired++; + AddRecoil(-0.4f * recoilAmplitude, -0.8f * recoilAmplitude, -0.3f * recoilAmplitude, 0.3f * recoilAmplitude); + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + aimRay.direction = Random.onUnitSphere; + HurtBox hurtBox = PickNextTarget(); + if ((bool)hurtBox) + { + aimRay.direction = hurtBox.transform.position - aimRay.origin; + } + Util.PlaySound(firePistolSoundString, base.gameObject); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.radius = 0.1f; + bulletAttack.smartCollision = true; + bulletAttack.Fire(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando/DeathState.cs new file mode 100644 index 0000000..c878e07 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando/DeathState.cs @@ -0,0 +1,55 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Commando; + +public class DeathState : GenericCharacterDeath +{ + private Vector3 previousPosition; + + private float upSpeedVelocity; + + private float upSpeed; + + private Animator modelAnimator; + + protected override bool shouldAutoDestroy => false; + + public override void OnEnter() + { + base.OnEnter(); + Vector3 force = Vector3.up * 3f; + if ((bool)base.characterMotor) + { + force += base.characterMotor.velocity; + base.characterMotor.enabled = false; + } + if ((bool)base.cachedModelTransform) + { + RagdollController component = base.cachedModelTransform.GetComponent(); + if ((bool)component) + { + component.BeginRagdoll(force); + } + } + } + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge > 4f) + { + EntityState.Destroy(base.gameObject); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando/DodgeState.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando/DodgeState.cs new file mode 100644 index 0000000..a70d0e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando/DodgeState.cs @@ -0,0 +1,174 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Commando; + +public class DodgeState : BaseState +{ + [SerializeField] + public float duration = 0.9f; + + [SerializeField] + public float initialSpeedCoefficient; + + [SerializeField] + public float finalSpeedCoefficient; + + public static string dodgeSoundString; + + public static GameObject jetEffect; + + public static float dodgeFOV; + + public static int primaryReloadStockCount; + + private float rollSpeed; + + private Vector3 forwardDirection; + + private Animator animator; + + private Vector3 previousPosition; + + private static int DodgeForwardStateHash = Animator.StringToHash("DodgeForward"); + + private static int DodgeBackwardStateHash = Animator.StringToHash("DodgeBackward"); + + private static int DodgeRightStateHash = Animator.StringToHash("DodgeRight"); + + private static int DodgeLeftStateHash = Animator.StringToHash("DodgeLeft"); + + private static int DodgeParamHash = Animator.StringToHash("Dodge.playbackRate"); + + public override void Reset() + { + base.Reset(); + rollSpeed = 0f; + forwardDirection = Vector3.zero; + animator = null; + previousPosition = Vector3.zero; + } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(dodgeSoundString, base.gameObject); + animator = GetModelAnimator(); + ChildLocator component = animator.GetComponent(); + if (base.isAuthority) + { + if ((bool)base.inputBank && (bool)base.characterDirection) + { + forwardDirection = ((base.inputBank.moveVector == Vector3.zero) ? base.characterDirection.forward : base.inputBank.moveVector).normalized; + } + if ((bool)base.skillLocator.primary) + { + base.skillLocator.primary.Reset(); + base.skillLocator.primary.stock = primaryReloadStockCount; + } + } + Vector3 rhs = (base.characterDirection ? base.characterDirection.forward : forwardDirection); + Vector3 rhs2 = Vector3.Cross(Vector3.up, rhs); + float num = Vector3.Dot(forwardDirection, rhs); + float num2 = Vector3.Dot(forwardDirection, rhs2); + animator.SetFloat("forwardSpeed", num, 0.1f, GetDeltaTime()); + animator.SetFloat("rightSpeed", num2, 0.1f, GetDeltaTime()); + if (Mathf.Abs(num) > Mathf.Abs(num2)) + { + PlayAnimation("Body", (num > 0f) ? DodgeForwardStateHash : DodgeBackwardStateHash, DodgeParamHash, duration); + } + else + { + PlayAnimation("Body", (num2 > 0f) ? DodgeRightStateHash : DodgeLeftStateHash, DodgeParamHash, duration); + } + if ((bool)jetEffect) + { + Transform transform = component.FindChild("LeftJet"); + Transform transform2 = component.FindChild("RightJet"); + bool flag = EffectManager.ShouldUsePooledEffect(jetEffect); + if ((bool)transform) + { + if (!flag) + { + Object.Instantiate(jetEffect, transform); + } + else + { + EffectManager.GetAndActivatePooledEffect(jetEffect, transform, inResetLocal: true); + } + } + if ((bool)transform2) + { + if (!flag) + { + Object.Instantiate(jetEffect, transform2); + } + else + { + EffectManager.GetAndActivatePooledEffect(jetEffect, transform2, inResetLocal: true); + } + } + } + RecalculateRollSpeed(); + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.velocity.y = 0f; + base.characterMotor.velocity = forwardDirection * rollSpeed; + } + Vector3 vector = (base.characterMotor ? base.characterMotor.velocity : Vector3.zero); + previousPosition = base.transform.position - vector; + } + + private void RecalculateRollSpeed() + { + rollSpeed = moveSpeedStat * Mathf.Lerp(initialSpeedCoefficient, finalSpeedCoefficient, base.fixedAge / duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + RecalculateRollSpeed(); + if ((bool)base.cameraTargetParams) + { + base.cameraTargetParams.fovOverride = Mathf.Lerp(dodgeFOV, 60f, base.fixedAge / duration); + } + Vector3 normalized = (base.transform.position - previousPosition).normalized; + if ((bool)base.characterMotor && (bool)base.characterDirection && normalized != Vector3.zero) + { + Vector3 lhs = normalized * rollSpeed; + float y = lhs.y; + lhs.y = 0f; + float num = Mathf.Max(Vector3.Dot(lhs, forwardDirection), 0f); + lhs = forwardDirection * num; + lhs.y += Mathf.Max(y, 0f); + base.characterMotor.velocity = lhs; + } + previousPosition = base.transform.position; + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)base.cameraTargetParams) + { + base.cameraTargetParams.fovOverride = -1f; + } + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(forwardDirection); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + forwardDirection = reader.ReadVector3(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando/MainState.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando/MainState.cs new file mode 100644 index 0000000..979a9d2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando/MainState.cs @@ -0,0 +1,195 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando; + +public class MainState : BaseState +{ + private Animator modelAnimator; + + private GenericSkill skill1; + + private GenericSkill skill2; + + private GenericSkill skill3; + + private GenericSkill skill4; + + private bool skill1InputRecieved; + + private bool skill2InputRecieved; + + private bool skill3InputRecieved; + + private bool skill4InputRecieved; + + private Vector3 previousPosition; + + private Vector3 estimatedVelocity; + + private static int isMovingParamHash = Animator.StringToHash("isMoving"); + + private static int walkSpeedParamHash = Animator.StringToHash("walkSpeed"); + + private static int forwardSpeedParamHash = Animator.StringToHash("forwardSpeed"); + + private static int rightSpeedParamHash = Animator.StringToHash("rightSpeed"); + + public override void OnEnter() + { + base.OnEnter(); + GenericSkill[] components = base.gameObject.GetComponents(); + for (int i = 0; i < components.Length; i++) + { + if (components[i].skillName == "FirePistol") + { + skill1 = components[i]; + } + else if (components[i].skillName == "FireFMJ") + { + skill2 = components[i]; + } + else if (components[i].skillName == "Roll") + { + skill3 = components[i]; + } + else if (components[i].skillName == "FireBarrage") + { + skill4 = components[i]; + } + } + modelAnimator = GetModelAnimator(); + previousPosition = base.transform.position; + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.CrossFadeInFixedTime("Walk", 0.1f, layerIndex); + modelAnimator.Update(0f); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + } + } + + public override void OnExit() + { + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = false; + } + } + if (base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.moveDirection = Vector3.zero; + } + base.OnExit(); + } + + public override void Update() + { + base.Update(); + if (base.inputBank.skill1.down) + { + skill1InputRecieved = true; + } + if (base.inputBank.skill2.down) + { + skill2InputRecieved = true; + } + if (base.inputBank.skill3.down) + { + skill3InputRecieved = true; + } + if (base.inputBank.skill4.down) + { + skill4InputRecieved = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + Vector3 position = base.transform.position; + float deltaTime = GetDeltaTime(); + if (deltaTime != 0f) + { + estimatedVelocity = (position - previousPosition) / deltaTime; + } + if (base.isAuthority) + { + Vector3 moveVector = base.inputBank.moveVector; + if ((bool)base.characterMotor) + { + base.characterMotor.moveDirection = moveVector; + if (skill3InputRecieved) + { + if ((bool)skill3) + { + skill3.ExecuteIfReady(); + } + skill3InputRecieved = false; + } + } + if ((bool)base.characterDirection) + { + if ((bool)base.characterBody && base.characterBody.shouldAim) + { + base.characterDirection.moveVector = base.inputBank.aimDirection; + } + else + { + base.characterDirection.moveVector = moveVector; + } + } + if (skill1InputRecieved) + { + if ((bool)skill1) + { + skill1.ExecuteIfReady(); + } + skill1InputRecieved = false; + } + if (skill2InputRecieved) + { + if ((bool)skill2) + { + skill2.ExecuteIfReady(); + } + skill2InputRecieved = false; + } + if (skill4InputRecieved) + { + if ((bool)skill4) + { + skill4.ExecuteIfReady(); + } + skill4InputRecieved = false; + } + } + if ((bool)modelAnimator && (bool)base.characterDirection) + { + Vector3 lhs = estimatedVelocity; + lhs.y = 0f; + Vector3 forward = base.characterDirection.forward; + Vector3 rhs = Vector3.Cross(Vector3.up, forward); + float magnitude = lhs.magnitude; + float value = Vector3.Dot(lhs, forward); + float value2 = Vector3.Dot(lhs, rhs); + modelAnimator.SetBool(isMovingParamHash, magnitude != 0f); + modelAnimator.SetFloat(walkSpeedParamHash, magnitude); + modelAnimator.SetFloat(forwardSpeedParamHash, value, 0.2f, GetDeltaTime()); + modelAnimator.SetFloat(rightSpeedParamHash, value2, 0.2f, GetDeltaTime()); + } + previousPosition = position; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Commando/SlideState.cs b/ilspy_dump/ror2_csproj/EntityStates.Commando/SlideState.cs new file mode 100644 index 0000000..30602b3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Commando/SlideState.cs @@ -0,0 +1,124 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Commando; + +public class SlideState : BaseState +{ + public static float slideDuration; + + public static float jumpDuration; + + public static AnimationCurve forwardSpeedCoefficientCurve; + + public static AnimationCurve jumpforwardSpeedCoefficientCurve; + + public static string soundString; + + public static GameObject jetEffectPrefab; + + public static GameObject slideEffectPrefab; + + private Vector3 forwardDirection; + + private GameObject slideEffectInstance; + + private bool startedStateGrounded; + + private static int JumpStateHash = Animator.StringToHash("Jump"); + + private static int SlideForwardStateHash = Animator.StringToHash("SlideForward"); + + private static int SlideForwardParamHash = Animator.StringToHash("SlideForward.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundString, base.gameObject); + if ((bool)base.inputBank && (bool)base.characterDirection) + { + base.characterDirection.forward = ((base.inputBank.moveVector == Vector3.zero) ? base.characterDirection.forward : base.inputBank.moveVector).normalized; + } + if ((bool)base.characterMotor) + { + startedStateGrounded = base.characterMotor.isGrounded; + } + if ((bool)jetEffectPrefab) + { + Transform transform = FindModelChild("LeftJet"); + Transform transform2 = FindModelChild("RightJet"); + if ((bool)transform) + { + Object.Instantiate(jetEffectPrefab, transform); + } + if ((bool)transform2) + { + Object.Instantiate(jetEffectPrefab, transform2); + } + } + base.characterBody.SetSpreadBloom(0f, canOnlyIncreaseBloom: false); + if (!startedStateGrounded) + { + PlayAnimation("Body", JumpStateHash); + Vector3 velocity = base.characterMotor.velocity; + velocity.y = base.characterBody.jumpPower; + base.characterMotor.velocity = velocity; + return; + } + PlayAnimation("Body", SlideForwardStateHash, SlideForwardParamHash, slideDuration); + if ((bool)slideEffectPrefab) + { + Transform parent = FindModelChild("Base"); + slideEffectInstance = Object.Instantiate(slideEffectPrefab, parent); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + float num = (startedStateGrounded ? slideDuration : jumpDuration); + if ((bool)base.inputBank && (bool)base.characterDirection) + { + base.characterDirection.moveVector = base.inputBank.moveVector; + forwardDirection = base.characterDirection.forward; + } + if ((bool)base.characterMotor) + { + float num2 = 0f; + num2 = ((!startedStateGrounded) ? jumpforwardSpeedCoefficientCurve.Evaluate(base.fixedAge / num) : forwardSpeedCoefficientCurve.Evaluate(base.fixedAge / num)); + base.characterMotor.rootMotion += num2 * moveSpeedStat * forwardDirection * GetDeltaTime(); + } + if (base.fixedAge >= num) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + PlayImpactAnimation(); + if ((bool)slideEffectInstance) + { + EntityState.Destroy(slideEffectInstance); + } + base.OnExit(); + } + + private void PlayImpactAnimation() + { + Animator modelAnimator = GetModelAnimator(); + int layerIndex = modelAnimator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + modelAnimator.SetLayerWeight(layerIndex, 1f); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/BaseLeap.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/BaseLeap.cs new file mode 100644 index 0000000..a925a3f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/BaseLeap.cs @@ -0,0 +1,221 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Croco; + +public class BaseLeap : BaseCharacterMain +{ + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastForce; + + public static string leapSoundString; + + public static GameObject projectilePrefab; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public GameObject blastImpactEffectPrefab; + + [SerializeField] + public GameObject blastEffectPrefab; + + public static float airControl; + + public static float aimVelocity; + + public static float upwardVelocity; + + public static float forwardVelocity; + + public static float minimumY; + + public static float minYVelocityForAnim; + + public static float maxYVelocityForAnim; + + public static float knockbackForce; + + [SerializeField] + public GameObject fistEffectPrefab; + + public static string soundLoopStartEvent; + + public static string soundLoopStopEvent; + + public static NetworkSoundEventDef landingSound; + + private float previousAirControl; + + private GameObject leftFistEffectInstance; + + private GameObject rightFistEffectInstance; + + protected bool isCritAuthority; + + protected CrocoDamageTypeController crocoDamageTypeController; + + private bool detonateNextFrame; + + private static int LightImpactStateHash = Animator.StringToHash("LightImpact"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + protected virtual DamageTypeCombo GetBlastDamageType() + { + return DamageType.Generic; + } + + public override void OnEnter() + { + base.OnEnter(); + crocoDamageTypeController = GetComponent(); + previousAirControl = base.characterMotor.airControl; + base.characterMotor.airControl = airControl; + Vector3 direction = GetAimRay().direction; + if (base.isAuthority) + { + base.characterBody.isSprinting = true; + direction.y = Mathf.Max(direction.y, minimumY); + Vector3 vector = direction.normalized * aimVelocity * moveSpeedStat; + Vector3 vector2 = Vector3.up * upwardVelocity; + Vector3 vector3 = new Vector3(direction.x, 0f, direction.z).normalized * forwardVelocity; + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.velocity = vector + vector2 + vector3; + isCritAuthority = RollCrit(); + } + base.characterBody.bodyFlags |= CharacterBody.BodyFlags.IgnoreFallDamage; + GetModelTransform().GetComponent().enabled = true; + PlayCrossfade("Gesture, Override", "Leap", 0.1f); + PlayCrossfade("Gesture, AdditiveHigh", "Leap", 0.1f); + PlayCrossfade("Gesture, Override", "Leap", 0.1f); + Util.PlaySound(leapSoundString, base.gameObject); + base.characterDirection.moveVector = direction; + leftFistEffectInstance = Object.Instantiate(fistEffectPrefab, FindModelChild("MuzzleHandL")); + rightFistEffectInstance = Object.Instantiate(fistEffectPrefab, FindModelChild("MuzzleHandR")); + if (base.isAuthority) + { + base.characterMotor.onMovementHit += OnMovementHit; + } + Util.PlaySound(soundLoopStartEvent, base.gameObject); + } + + private void OnMovementHit(ref CharacterMotor.MovementHitInfo movementHitInfo) + { + detonateNextFrame = true; + } + + private void onHitGroundServer(ref CharacterMotor.HitGroundInfo hitGroundInfo) + { + detonateNextFrame = true; + } + + protected override void UpdateAnimationParameters() + { + base.UpdateAnimationParameters(); + float value = Mathf.Clamp01(Util.Remap(base.estimatedVelocity.y, minYVelocityForAnim, maxYVelocityForAnim, 0f, 1f)) * 0.97f; + base.modelAnimator.SetFloat("LeapCycle", value, 0.1f, Time.deltaTime); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.moveDirection = base.inputBank.moveVector; + if (base.fixedAge >= minimumDuration && (detonateNextFrame || (base.characterMotor.Motor.GroundingStatus.IsStableOnGround && !base.characterMotor.Motor.LastGroundingStatus.IsStableOnGround))) + { + DoImpactAuthority(); + outer.SetNextStateToMain(); + } + } + } + + protected virtual void DoImpactAuthority() + { + if ((bool)landingSound) + { + EffectManager.SimpleSoundEffect(landingSound.index, base.characterBody.footPosition, transmit: true); + } + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 footPosition = base.characterBody.footPosition; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = footPosition, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = isCritAuthority, + damageType = GetBlastDamageType(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = footPosition, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + protected void DropAcidPoolAuthority() + { + Vector3 footPosition = base.characterBody.footPosition; + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.crit = isCritAuthority; + fireProjectileInfo.force = 0f; + fireProjectileInfo.damage = damageStat; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.position = footPosition; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + + public override void OnExit() + { + Util.PlaySound(soundLoopStopEvent, base.gameObject); + if (base.isAuthority) + { + base.characterMotor.onMovementHit -= OnMovementHit; + } + base.characterBody.bodyFlags &= ~CharacterBody.BodyFlags.IgnoreFallDamage; + base.characterMotor.airControl = previousAirControl; + base.characterBody.isSprinting = false; + int layerIndex = base.modelAnimator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + base.modelAnimator.SetLayerWeight(layerIndex, 2f); + PlayAnimation("Impact", LightImpactStateHash); + } + PlayCrossfade("Gesture, Override", BufferEmptyStateHash, 0.1f); + PlayCrossfade("Gesture, AdditiveHigh", BufferEmptyStateHash, 0.1f); + EntityState.Destroy(leftFistEffectInstance); + EntityState.Destroy(rightFistEffectInstance); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/Bite.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/Bite.cs new file mode 100644 index 0000000..7962e91 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/Bite.cs @@ -0,0 +1,90 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Croco; + +public class Bite : BasicMeleeAttack +{ + public static float recoilAmplitude; + + public static float baseDurationBeforeInterruptable; + + [SerializeField] + public float bloom; + + public static string biteSound; + + private string animationStateName; + + private float durationBeforeInterruptable; + + private CrocoDamageTypeController crocoDamageTypeController; + + private bool hasGrantedBuff; + + protected override bool allowExitFire + { + get + { + if ((bool)base.characterBody) + { + return !base.characterBody.isSprinting; + } + return false; + } + } + + public override void OnEnter() + { + base.OnEnter(); + base.characterDirection.forward = GetAimRay().direction; + durationBeforeInterruptable = baseDurationBeforeInterruptable / attackSpeedStat; + crocoDamageTypeController = GetComponent(); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + DamageTypeCombo damageTypeCombo = (crocoDamageTypeController ? crocoDamageTypeController.GetDamageType() : DamageTypeCombo.Generic); + overlapAttack.damageType = damageTypeCombo | DamageType.BonusToLowHealth; + } + + protected override void PlayAnimation() + { + float num = Mathf.Max(duration, 0.2f); + PlayCrossfade("Gesture, Additive", "Bite", "Bite.playbackRate", num, 0.05f); + PlayCrossfade("Gesture, Override", "Bite", "Bite.playbackRate", num, 0.05f); + Util.PlaySound(biteSound, base.gameObject); + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + base.characterBody.AddSpreadBloom(bloom); + if (!hasGrantedBuff) + { + hasGrantedBuff = true; + base.characterBody.AddTimedBuffAuthority(RoR2Content.Buffs.CrocoRegen.buffIndex, 0.5f); + } + } + + protected override void BeginMeleeAttackEffect() + { + AddRecoil(0.9f * recoilAmplitude, 1.1f * recoilAmplitude, -0.1f * recoilAmplitude, 0.1f * recoilAmplitude); + base.BeginMeleeAttackEffect(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge < durationBeforeInterruptable)) + { + return InterruptPriority.Skill; + } + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/ChainableLeap.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/ChainableLeap.cs new file mode 100644 index 0000000..6f3c3a3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/ChainableLeap.cs @@ -0,0 +1,20 @@ +using RoR2; + +namespace EntityStates.Croco; + +public class ChainableLeap : BaseLeap +{ + public static float refundPerHit; + + protected override DamageTypeCombo GetBlastDamageType() + { + return DamageType.Stun1s; + } + + protected override void DoImpactAuthority() + { + base.DoImpactAuthority(); + BlastAttack.Result result = DetonateAuthority(); + base.skillLocator.utility.RunRecharge((float)result.hitCount * refundPerHit); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/Disease.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/Disease.cs new file mode 100644 index 0000000..a1991b1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/Disease.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; + +namespace EntityStates.Croco; + +public class Disease : BaseState +{ + public static GameObject muzzleflashEffectPrefab; + + public static string muzzleString; + + public static float orbRange; + + public static float baseDuration; + + public static float damageCoefficient; + + public static int maxBounces; + + public static float bounceRange; + + public static float procCoefficient; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + Transform transform = FindModelChild(muzzleString); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.maxDistanceFilter = orbRange; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(TeamComponent.GetObjectTeam(base.gameObject)); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.RefreshCandidates(); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + List list = bullseyeSearch.GetResults().ToList(); + if (list.Count > 0) + { + Debug.LogFormat("Shooting at {0}", list[0]); + HurtBox target = list.FirstOrDefault(); + LightningOrb lightningOrb = new LightningOrb(); + lightningOrb.attacker = base.gameObject; + lightningOrb.bouncedObjects = new List(); + lightningOrb.lightningType = LightningOrb.LightningType.CrocoDisease; + lightningOrb.damageType = DamageType.PoisonOnHit; + lightningOrb.damageValue = damageStat * damageCoefficient; + lightningOrb.isCrit = RollCrit(); + lightningOrb.procCoefficient = procCoefficient; + lightningOrb.bouncesRemaining = maxBounces; + lightningOrb.origin = transform.position; + lightningOrb.target = target; + lightningOrb.teamIndex = GetTeam(); + lightningOrb.range = bounceRange; + OrbManager.instance.AddOrb(lightningOrb); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/FireDiseaseProjectile.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/FireDiseaseProjectile.cs new file mode 100644 index 0000000..7bd4b33 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/FireDiseaseProjectile.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Croco; + +public class FireDiseaseProjectile : FireSpit +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/FireSpit.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/FireSpit.cs new file mode 100644 index 0000000..6accd3d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/FireSpit.cs @@ -0,0 +1,92 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Croco; + +public class FireSpit : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + private float duration; + + private CrocoDamageTypeController crocoDamageTypeController; + + private static int FireSpitStateHash = Animator.StringToHash("FireSpit"); + + private static int FireSpitParamHash = Animator.StringToHash("FireSpit.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + crocoDamageTypeController = GetComponent(); + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + duration = baseDuration / attackSpeedStat; + StartAimMode(duration + 2f); + PlayAnimation("Gesture, Mouth", FireSpitStateHash, FireSpitParamHash, duration); + Util.PlaySound(attackString, base.gameObject); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + string muzzleName = "MouthMuzzle"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + DamageTypeCombo value = (crocoDamageTypeController ? crocoDamageTypeController.GetDamageType() : DamageTypeCombo.Generic); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.damageTypeOverride = value; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/Leap.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/Leap.cs new file mode 100644 index 0000000..9ea610e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/Leap.cs @@ -0,0 +1,18 @@ +using RoR2; + +namespace EntityStates.Croco; + +public class Leap : BaseLeap +{ + protected override DamageTypeCombo GetBlastDamageType() + { + return (crocoDamageTypeController ? crocoDamageTypeController.GetDamageType() : DamageTypeCombo.Generic) | DamageType.Stun1s; + } + + protected override void DoImpactAuthority() + { + base.DoImpactAuthority(); + DetonateAuthority(); + DropAcidPoolAuthority(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/Slash.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/Slash.cs new file mode 100644 index 0000000..c9650c3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/Slash.cs @@ -0,0 +1,145 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Croco; + +public class Slash : BasicMeleeAttack, SteppedSkillDef.IStepSetter +{ + public int step; + + public static float recoilAmplitude; + + public static float baseDurationBeforeInterruptable; + + [SerializeField] + public float bloom; + + public static GameObject comboFinisherSwingEffectPrefab; + + public static float comboFinisherhitPauseDuration; + + public static float comboFinisherDamageCoefficient; + + public static float comboFinisherBloom; + + public static float comboFinisherBaseDurationBeforeInterruptable; + + public static string slash1Sound; + + public static string slash3Sound; + + private string animationStateName; + + private float durationBeforeInterruptable; + + private bool hasGrantedBuff; + + private bool isComboFinisher => step == 2; + + protected override bool allowExitFire + { + get + { + if ((bool)base.characterBody) + { + return !base.characterBody.isSprinting; + } + return false; + } + } + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + step = i; + } + + public override void OnEnter() + { + if (isComboFinisher) + { + swingEffectPrefab = comboFinisherSwingEffectPrefab; + hitPauseDuration = comboFinisherhitPauseDuration; + damageCoefficient = comboFinisherDamageCoefficient; + bloom = comboFinisherBloom; + } + base.OnEnter(); + base.characterDirection.forward = GetAimRay().direction; + durationBeforeInterruptable = (isComboFinisher ? (comboFinisherBaseDurationBeforeInterruptable / attackSpeedStat) : (baseDurationBeforeInterruptable / attackSpeedStat)); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + } + + protected override void PlayAnimation() + { + animationStateName = ""; + string soundString = null; + switch (step) + { + case 0: + animationStateName = "Slash1"; + soundString = slash1Sound; + break; + case 1: + animationStateName = "Slash2"; + soundString = slash1Sound; + break; + case 2: + animationStateName = "Slash3"; + soundString = slash3Sound; + break; + } + float num = Mathf.Max(duration, 0.2f); + PlayCrossfade("Gesture, Additive", animationStateName, "Slash.playbackRate", num, 0.05f); + PlayCrossfade("Gesture, Override", animationStateName, "Slash.playbackRate", num, 0.05f); + Util.PlaySound(soundString, base.gameObject); + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + base.characterBody.AddSpreadBloom(bloom); + if (!hasGrantedBuff && isComboFinisher) + { + hasGrantedBuff = true; + base.characterBody.AddTimedBuffAuthority(RoR2Content.Buffs.CrocoRegen.buffIndex, 0.5f); + } + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectMuzzleString = animationStateName; + AddRecoil(-0.1f * recoilAmplitude, 0.1f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + base.BeginMeleeAttackEffect(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)step); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + step = reader.ReadByte(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge < durationBeforeInterruptable)) + { + return InterruptPriority.Skill; + } + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/Spawn.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/Spawn.cs new file mode 100644 index 0000000..14c130a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/Spawn.cs @@ -0,0 +1,49 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Croco; + +public class Spawn : BaseState +{ + public static float minimumSleepDuration; + + public static GameObject spawnEffectPrefab; + + private Animator modelAnimator; + + private static int SleepLoopStateHash = Animator.StringToHash("SleepLoop"); + + public override void OnEnter() + { + base.OnEnter(); + base.modelLocator.normalizeToFloor = true; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(AnimationParameters.aimWeight, 0f); + } + PlayAnimation("Body", SleepLoopStateHash); + EffectManager.SpawnEffect(spawnEffectPrefab, new EffectData + { + origin = base.characterBody.footPosition + }, transmit: false); + } + + public override void OnExit() + { + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(AnimationParameters.aimWeight, 1f); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= minimumSleepDuration && (base.inputBank.moveVector.sqrMagnitude >= Mathf.Epsilon || base.inputBank.CheckAnyButtonDown())) + { + outer.SetNextState(new WakeUp()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Croco/WakeUp.cs b/ilspy_dump/ror2_csproj/EntityStates.Croco/WakeUp.cs new file mode 100644 index 0000000..b743e50 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Croco/WakeUp.cs @@ -0,0 +1,56 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Croco; + +public class WakeUp : BaseState +{ + public static float duration; + + public static float delayBeforeAimAnimatorWeight; + + private Animator modelAnimator; + + private static int SleepToIdleStateHash = Animator.StringToHash("SleepToIdle"); + + private static int SleepToIdleParamHash = Animator.StringToHash("SleepToIdle.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + base.modelLocator.normalizeToFloor = true; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(AnimationParameters.aimWeight, 0f); + } + PlayAnimation("Body", SleepToIdleStateHash, SleepToIdleParamHash, duration); + } + + public override void Update() + { + base.Update(); + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(AnimationParameters.aimWeight, Mathf.Clamp01((base.age - delayBeforeAimAnimatorWeight) / duration)); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(AnimationParameters.aimWeight, 1f); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/BaseDeepVoidPortalBatteryState.cs b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/BaseDeepVoidPortalBatteryState.cs new file mode 100644 index 0000000..edef16e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/BaseDeepVoidPortalBatteryState.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.DeepVoidPortalBattery; + +public class BaseDeepVoidPortalBatteryState : BaseState +{ + [SerializeField] + public string onEnterSoundString; + + [SerializeField] + public string onEnterChildToEnable; + + [SerializeField] + public string animationStateName; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(onEnterSoundString, base.gameObject); + GameObject gameObject = FindModelChildGameObject(onEnterChildToEnable); + if ((bool)gameObject) + { + gameObject.SetActive(value: true); + } + PlayAnimation("Base", animationStateName); + } + + public override void OnExit() + { + GameObject gameObject = FindModelChildGameObject(onEnterChildToEnable); + if ((bool)gameObject) + { + gameObject.SetActive(value: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Charged.cs b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Charged.cs new file mode 100644 index 0000000..d14081f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Charged.cs @@ -0,0 +1,16 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.DeepVoidPortalBattery; + +public class Charged : BaseDeepVoidPortalBatteryState +{ + public override void OnEnter() + { + base.OnEnter(); + if ((bool)VoidStageMissionController.instance && NetworkServer.active) + { + VoidStageMissionController.instance.OnBatteryActivated(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Charging.cs b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Charging.cs new file mode 100644 index 0000000..a49b2dd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Charging.cs @@ -0,0 +1,79 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.DeepVoidPortalBattery; + +public class Charging : BaseDeepVoidPortalBatteryState +{ + [SerializeField] + public GameObject chargingPositionIndicator; + + private CombatDirector combatDirector; + + private HoldoutZoneController holdoutZoneController; + + private VoidStageMissionController.FogRequest fogRequest; + + private ChargeIndicatorController chargeIndicatorController; + + public override void OnEnter() + { + base.OnEnter(); + holdoutZoneController = GetComponent(); + if ((bool)holdoutZoneController) + { + holdoutZoneController.enabled = true; + } + Transform targetTransform = FindModelChild("PositionIndicatorPosition").transform; + PositionIndicator component = Object.Instantiate(chargingPositionIndicator, base.transform.position, Quaternion.identity).GetComponent(); + component.targetTransform = targetTransform; + chargeIndicatorController = component.GetComponent(); + chargeIndicatorController.holdoutZoneController = holdoutZoneController; + if (NetworkServer.active) + { + combatDirector = GetComponent(); + if ((bool)combatDirector) + { + combatDirector.enabled = true; + combatDirector.SetNextSpawnAsBoss(); + } + if ((bool)holdoutZoneController && (bool)VoidStageMissionController.instance) + { + fogRequest = VoidStageMissionController.instance.RequestFog(holdoutZoneController); + } + } + } + + public override void OnExit() + { + if ((bool)chargeIndicatorController) + { + EntityState.Destroy(chargeIndicatorController.gameObject); + } + if ((bool)holdoutZoneController) + { + holdoutZoneController.enabled = false; + } + if (NetworkServer.active) + { + if ((bool)combatDirector) + { + combatDirector.enabled = false; + } + fogRequest?.Dispose(); + fogRequest = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && holdoutZoneController.charge >= 1f) + { + outer.SetNextState(new Charged()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Idle.cs b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Idle.cs new file mode 100644 index 0000000..04af563 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DeepVoidPortalBattery/Idle.cs @@ -0,0 +1,5 @@ +namespace EntityStates.DeepVoidPortalBattery; + +public class Idle : BaseDeepVoidPortalBatteryState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/AltarSkeletonDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/AltarSkeletonDeath.cs new file mode 100644 index 0000000..e003492 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/AltarSkeletonDeath.cs @@ -0,0 +1,62 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class AltarSkeletonDeath : BaseState +{ + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static string deathSoundString; + + private float stopwatch; + + public static event Action onDeath; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(deathSoundString, base.gameObject); + Explode(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + private void Explode() + { + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)explosionEffectPrefab && NetworkServer.active) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: false); + } + AltarSkeletonDeath.onDeath?.Invoke(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/CorruptedSpikeDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/CorruptedSpikeDeath.cs new file mode 100644 index 0000000..10c75e9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/CorruptedSpikeDeath.cs @@ -0,0 +1,71 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class CorruptedSpikeDeath : BaseState +{ + public static GameObject chargePrefab; + + public static float chargeDuration; + + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)chargePrefab) + { + Object.Instantiate(chargePrefab, base.transform); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= chargeDuration) + { + Explode(); + } + } + + private void Explode() + { + if ((bool)explosionEffectPrefab) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: true); + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = 1f; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/ExplosivePotDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/ExplosivePotDeath.cs new file mode 100644 index 0000000..25985c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/ExplosivePotDeath.cs @@ -0,0 +1,73 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class ExplosivePotDeath : BaseState +{ + public static GameObject chargePrefab; + + [Tooltip("How long the object will wait before exploding")] + public static float chargeDuration; + + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)chargePrefab) + { + Object.Instantiate(chargePrefab, base.transform); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= chargeDuration) + { + Explode(); + } + } + + public virtual void Explode() + { + if ((bool)explosionEffectPrefab) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: true); + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = damageStat * explosionDamageCoefficient * Run.instance.teamlessDamageCoefficient; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.damageType = DamageType.ClayGoo; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/FusionCellDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/FusionCellDeath.cs new file mode 100644 index 0000000..064bdb7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/FusionCellDeath.cs @@ -0,0 +1,91 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class FusionCellDeath : BaseState +{ + public static string chargeChildEffectName; + + public static float chargeDuration; + + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + private float stopwatch; + + public override void OnEnter() + { + base.OnEnter(); + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(chargeChildEffectName); + if ((bool)transform) + { + transform.gameObject.SetActive(value: true); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch > chargeDuration) + { + Explode(); + } + } + + private void Explode() + { + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)explosionEffectPrefab && NetworkServer.active) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: true); + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = damageStat * explosionDamageCoefficient * Run.instance.teamlessDamageCoefficient; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.bonusForce = explosionForce * 0.5f * Vector3.up; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/GauntletShardDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/GauntletShardDeath.cs new file mode 100644 index 0000000..7a4ebec --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/GauntletShardDeath.cs @@ -0,0 +1,75 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class GauntletShardDeath : BaseState +{ + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + private float stopwatch; + + public override void OnEnter() + { + base.OnEnter(); + Explode(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + } + + private void Explode() + { + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)explosionEffectPrefab && NetworkServer.active) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: true); + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = damageStat * explosionDamageCoefficient * Run.instance.teamlessDamageCoefficient; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.bonusForce = explosionForce * 0.5f * Vector3.up; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/LunarRainDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/LunarRainDeathState.cs new file mode 100644 index 0000000..30b2eb5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/LunarRainDeathState.cs @@ -0,0 +1,105 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class LunarRainDeathState : BaseState +{ + public static GameObject chargePrefab; + + [Tooltip("How long the object will wait before exploding")] + public static float chargeDuration; + + public static GameObject explosionEffectPrefab; + + public static float baseDamage; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + public static float vfxScale; + + public static bool canRejectForce; + + public override void OnEnter() + { + base.OnEnter(); + if (base.teamComponent != null) + { + base.teamComponent.teamIndex = TeamIndex.Monster; + } + if ((bool)chargePrefab) + { + EffectData effectData = new EffectData + { + scale = explosionRadius, + origin = base.transform.position + }; + EffectManager.SpawnEffect(chargePrefab, effectData, transmit: false); + } + FlashEmission component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + component.StartFlash(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= chargeDuration && NetworkServer.active) + { + Explode(); + } + } + + public virtual void Explode() + { + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)explosionEffectPrefab) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = vfxScale, + rotation = base.transform.rotation + }, transmit: true); + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = baseDamage * explosionDamageCoefficient * Run.instance.teamlessDamageCoefficient; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.Monster; + blastAttack.damageType = DamageType.LunarRuin; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.canRejectForce = canRejectForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/SulfurPodDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/SulfurPodDeath.cs new file mode 100644 index 0000000..86e2f61 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/SulfurPodDeath.cs @@ -0,0 +1,82 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class SulfurPodDeath : GenericCharacterDeath +{ + public static GameObject chargePrefab; + + public static float chargeDuration; + + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + private bool hasExploded; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)chargePrefab) + { + Object.Instantiate(chargePrefab, base.transform); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= chargeDuration) + { + Explode(); + } + } + + private void Explode() + { + if (!hasExploded) + { + hasExploded = true; + if ((bool)explosionEffectPrefab) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: true); + } + DestroyModel(); + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Poison; + blastAttack.baseDamage = damageStat * explosionDamageCoefficient * Run.instance.teamlessDamageCoefficient; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.damageType = DamageType.PoisonOnHit; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + DestroyBodyAsapServer(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Destructible/TimeCrystalDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Destructible/TimeCrystalDeath.cs new file mode 100644 index 0000000..2c15e5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Destructible/TimeCrystalDeath.cs @@ -0,0 +1,75 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Destructible; + +public class TimeCrystalDeath : BaseState +{ + public static GameObject explosionEffectPrefab; + + public static float explosionRadius; + + public static float explosionDamageCoefficient; + + public static float explosionProcCoefficient; + + public static float explosionForce; + + private float stopwatch; + + public override void OnEnter() + { + base.OnEnter(); + Explode(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + } + + private void Explode() + { + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)explosionEffectPrefab && NetworkServer.active) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = explosionRadius, + rotation = Quaternion.identity + }, transmit: true); + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = damageStat * explosionDamageCoefficient * Run.instance.teamlessDamageCoefficient; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.procCoefficient = explosionProcCoefficient; + blastAttack.teamIndex = TeamIndex.None; + blastAttack.position = base.transform.position; + blastAttack.baseForce = explosionForce; + blastAttack.bonusForce = explosionForce * 0.5f * Vector3.up; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireGatling.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireGatling.cs new file mode 100644 index 0000000..c6c516a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireGatling.cs @@ -0,0 +1,81 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Drone.DroneWeapon; + +public class FireGatling : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static float baseDuration = 2f; + + public static string fireGatlingSoundString; + + public int bulletCountCurrent = 1; + + private float duration; + + private static int FireGatlingStateHash = Animator.StringToHash("FireGatling"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + string muzzleName = "Muzzle"; + Util.PlaySound(fireGatlingSoundString, base.gameObject); + PlayAnimation("Gesture", FireGatlingStateHash); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireMegaTurret.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireMegaTurret.cs new file mode 100644 index 0000000..a911132 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireMegaTurret.cs @@ -0,0 +1,124 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Drone.DroneWeapon; + +public class FireMegaTurret : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static string attackSoundString; + + public static float attackSoundPlaybackCoefficient; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int maxBulletCount; + + public static float baseTotalDuration; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private float fireStopwatch; + + private float stopwatch; + + private float durationBetweenShots; + + private float totalDuration; + + private int bulletCount; + + private static int FireGatStateHash = Animator.StringToHash("FireGat"); + + public override void OnEnter() + { + base.OnEnter(); + fireStopwatch = 0f; + totalDuration = baseTotalDuration / attackSpeedStat; + durationBetweenShots = totalDuration / (float)maxBulletCount; + GetAimRay(); + Transform transform = GetModelTransform(); + if ((bool)transform) + { + childLocator = transform.GetComponent(); + } + } + + private void FireBullet(string muzzleString) + { + Ray aimRay = GetAimRay(); + _ = aimRay.origin; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSoundPlaybackCoefficient); + PlayAnimation("Gesture, Additive", FireGatStateHash); + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild(muzzleString); + if ((bool)transform) + { + _ = transform.position; + } + } + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleString; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + fireStopwatch += deltaTime; + stopwatch += deltaTime; + if (fireStopwatch >= durationBetweenShots) + { + bulletCount++; + fireStopwatch -= durationBetweenShots; + FireBullet((bulletCount % 2 == 0) ? "GatLeft" : "GatRight"); + } + if (stopwatch >= totalDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireMissileBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireMissileBarrage.cs new file mode 100644 index 0000000..bef3dc1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireMissileBarrage.cs @@ -0,0 +1,107 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Drone.DroneWeapon; + +public class FireMissileBarrage : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient = 1f; + + public static float baseFireInterval = 0.1f; + + public static float minSpread = 0f; + + public static float maxSpread = 5f; + + public static int maxMissileCount; + + private float fireTimer; + + private float fireInterval; + + private Transform modelTransform; + + private AimAnimator aimAnimator; + + private int missileCount; + + private static int FireMissileStateHash = Animator.StringToHash("FireMissile"); + + private void FireMissile(string targetMuzzle) + { + missileCount++; + PlayAnimation("Gesture, Additive", FireMissileStateHash); + Ray aimRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + aimRay.origin = transform.position; + } + } + } + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + if (base.isAuthority) + { + float x = Random.Range(minSpread, maxSpread); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, aimRay.direction); + Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y = vector.y; + vector.y = 0f; + float angle = Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * aimRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnEnter() + { + base.OnEnter(); + modelTransform = GetModelTransform(); + fireInterval = baseFireInterval / attackSpeedStat; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + FireMissile("Muzzle"); + fireTimer += fireInterval; + } + if (missileCount >= maxMissileCount && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireTurret.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireTurret.cs new file mode 100644 index 0000000..abdb0b2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireTurret.cs @@ -0,0 +1,88 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Drone.DroneWeapon; + +public class FireTurret : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static string attackSoundString; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float durationBetweenShots = 1f; + + public static float baseDuration = 2f; + + public int bulletCountCurrent = 1; + + private float duration = 2f; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + string muzzleName = "Muzzle"; + Util.PlaySound(attackSoundString, base.gameObject); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= durationBetweenShots / attackSpeedStat && bulletCountCurrent < bulletCount && base.isAuthority) + { + FireTurret fireTurret = new FireTurret(); + fireTurret.bulletCountCurrent = bulletCountCurrent + 1; + outer.SetNextState(fireTurret); + } + else if (base.fixedAge >= duration && bulletCountCurrent >= bulletCount && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireTwinRocket.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireTwinRocket.cs new file mode 100644 index 0000000..26c5df2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/FireTwinRocket.cs @@ -0,0 +1,86 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Drone.DroneWeapon; + +public class FireTwinRocket : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject muzzleEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float baseDuration = 2f; + + private ChildLocator childLocator; + + private float stopwatch; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + GetAimRay(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + } + FireProjectile("GatLeft"); + FireProjectile("GatRight"); + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireProjectile(string muzzleString) + { + GetAimRay(); + Transform transform = childLocator.FindChild(muzzleString); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (!base.isAuthority || !(projectilePrefab != null)) + { + return; + } + float maxDistance = 1000f; + Ray aimRay = GetAimRay(); + Vector3 forward = aimRay.direction; + Vector3 position = aimRay.origin; + if ((bool)transform) + { + position = transform.position; + if (Physics.Raycast(aimRay, out var hitInfo, maxDistance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask)) + { + forward = hitInfo.point - transform.position; + } + } + ProjectileManager.instance.FireProjectile(projectilePrefab, position, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration / attackSpeedStat && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/Flamethrower.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/Flamethrower.cs new file mode 100644 index 0000000..541c229 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/Flamethrower.cs @@ -0,0 +1,7 @@ +using EntityStates.Mage.Weapon; + +namespace EntityStates.Drone.DroneWeapon; + +public class Flamethrower : EntityStates.Mage.Weapon.Flamethrower +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/HealBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/HealBeam.cs new file mode 100644 index 0000000..4aedcc8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/HealBeam.cs @@ -0,0 +1,98 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Drone.DroneWeapon; + +public class HealBeam : BaseState +{ + public static float baseDuration; + + public static float healCoefficient = 5f; + + public static GameObject healBeamPrefab; + + public HurtBox target; + + private HealBeamController healBeamController; + + private float duration; + + private float lineWidthRefVelocity; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Gesture", "Heal", 0.2f); + duration = baseDuration / attackSpeedStat; + float healRate = healCoefficient * damageStat / duration; + Ray aimRay = GetAimRay(); + Transform transform = FindModelChild("Muzzle"); + if (NetworkServer.active) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.none; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.AddTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.filterByLoS = false; + bullseyeSearch.maxDistanceFilter = 50f; + bullseyeSearch.maxAngleFilter = 180f; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + target = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)transform && (bool)target) + { + GameObject gameObject = Object.Instantiate(healBeamPrefab, transform); + healBeamController = gameObject.GetComponent(); + healBeamController.healRate = healRate; + healBeamController.target = target; + healBeamController.ownership.ownerObject = base.gameObject; + NetworkServer.Spawn(gameObject); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((base.fixedAge >= duration || !target) && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + PlayCrossfade("Gesture", "Empty", 0.2f); + if ((bool)healBeamController) + { + healBeamController.BreakServer(); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + HurtBoxReference.FromHurtBox(target).Write(writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + HurtBoxReference hurtBoxReference = default(HurtBoxReference); + hurtBoxReference.Read(reader); + target = hurtBoxReference.ResolveGameObject()?.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/StartHealBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/StartHealBeam.cs new file mode 100644 index 0000000..83763d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone.DroneWeapon/StartHealBeam.cs @@ -0,0 +1,111 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Drone.DroneWeapon; + +public class StartHealBeam : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float targetSelectionRange; + + [SerializeField] + public float healRateCoefficient; + + [SerializeField] + public GameObject healBeamPrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public int maxSimultaneousBeams; + + private HurtBox targetHurtBox; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + targetHurtBox = FindTarget(aimRay); + } + if (NetworkServer.active && HealBeamController.GetHealBeamCountForOwner(base.gameObject) < maxSimultaneousBeams && (bool)targetHurtBox) + { + Transform transform = FindModelChild(muzzleName); + if ((bool)transform) + { + GameObject obj = Object.Instantiate(healBeamPrefab, transform); + HealBeamController component = obj.GetComponent(); + component.healRate = healRateCoefficient * damageStat * attackSpeedStat; + component.target = targetHurtBox; + component.ownership.ownerObject = base.gameObject; + obj.AddComponent().duration = duration; + NetworkServer.Spawn(obj); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private HurtBox FindTarget(Ray aimRay) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.none; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.AddTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.filterByLoS = false; + bullseyeSearch.maxDistanceFilter = targetSelectionRange; + bullseyeSearch.maxAngleFilter = 180f; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + return bullseyeSearch.GetResults().Where(NotAlreadyHealingTarget).Where(IsHurt) + .FirstOrDefault(); + } + + private bool NotAlreadyHealingTarget(HurtBox hurtBox) + { + return !HealBeamController.HealBeamAlreadyExists(base.gameObject, hurtBox); + } + + private static bool IsHurt(HurtBox hurtBox) + { + if (hurtBox.healthComponent.alive) + { + return hurtBox.healthComponent.health < hurtBox.healthComponent.fullHealth; + } + return false; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(HurtBoxReference.FromHurtBox(targetHurtBox)); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + targetHurtBox = reader.ReadHurtBoxReference().ResolveHurtBox(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone/DeathState.cs new file mode 100644 index 0000000..6ad74c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone/DeathState.cs @@ -0,0 +1,133 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Drone; + +public class DeathState : GenericCharacterDeath +{ + public class RigidbodyCollisionListener : MonoBehaviour + { + public DeathState deathState; + + private void OnCollisionEnter(Collision collision) + { + deathState.OnImpactServer(collision.GetContact(0).point); + deathState.Explode(); + } + } + + [SerializeField] + public GameObject initialExplosionEffect; + + [SerializeField] + public GameObject deathExplosionEffect; + + [SerializeField] + public string initialSoundString; + + [SerializeField] + public string deathSoundString; + + [SerializeField] + public float deathEffectRadius; + + [SerializeField] + public float forceAmount = 20f; + + [SerializeField] + public float deathDuration = 2f; + + [SerializeField] + public bool destroyOnImpact; + + private RigidbodyCollisionListener rigidbodyCollisionListener; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(initialSoundString, base.gameObject); + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.forcePID.enabled = false; + base.rigidbodyMotor.rigid.useGravity = true; + base.rigidbodyMotor.rigid.AddForce(Vector3.up * forceAmount, ForceMode.Force); + base.rigidbodyMotor.rigid.collisionDetectionMode = CollisionDetectionMode.Continuous; + } + if ((bool)base.rigidbodyDirection) + { + base.rigidbodyDirection.enabled = false; + } + if ((bool)initialExplosionEffect) + { + EffectManager.SpawnEffect(deathExplosionEffect, new EffectData + { + origin = base.characterBody.corePosition, + scale = base.characterBody.radius + deathEffectRadius + }, transmit: false); + } + if (base.isAuthority && destroyOnImpact) + { + rigidbodyCollisionListener = base.gameObject.AddComponent(); + rigidbodyCollisionListener.deathState = this; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge > deathDuration) + { + Explode(); + } + } + + public void Explode() + { + EntityState.Destroy(base.gameObject); + } + + public virtual void OnImpactServer(Vector3 contactPoint) + { + string bodyName = BodyCatalog.GetBodyName(base.characterBody.bodyIndex); + bodyName = bodyName.Replace("Body", ""); + bodyName = "iscBroken" + bodyName; + SpawnCard spawnCard = LegacyResourcesAPI.Load("SpawnCards/InteractableSpawnCard/" + bodyName); + if (!(spawnCard != null)) + { + return; + } + DirectorPlacementRule placementRule = new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Direct, + position = contactPoint + }; + GameObject gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(spawnCard, placementRule, new Xoroshiro128Plus(0uL))); + if ((bool)gameObject) + { + PurchaseInteraction component = gameObject.GetComponent(); + if ((bool)component && component.costType == CostTypeIndex.Money) + { + component.Networkcost = Run.instance.GetDifficultyScaledCost(component.cost); + } + } + } + + public override void OnExit() + { + if ((bool)deathExplosionEffect) + { + EffectManager.SpawnEffect(deathExplosionEffect, new EffectData + { + origin = base.characterBody.corePosition, + scale = base.characterBody.radius + deathEffectRadius + }, transmit: false); + } + if ((bool)rigidbodyCollisionListener) + { + EntityState.Destroy(rigidbodyCollisionListener); + } + Util.PlaySound(deathSoundString, base.gameObject); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Drone/MegaDroneDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Drone/MegaDroneDeathState.cs new file mode 100644 index 0000000..f498d88 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Drone/MegaDroneDeathState.cs @@ -0,0 +1,62 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Drone; + +public class MegaDroneDeathState : GenericCharacterDeath +{ + public static string initialSoundString; + + public static GameObject initialEffect; + + public static float initialEffectScale; + + public static float velocityMagnitude; + + public static float explosionForce; + + public override void OnEnter() + { + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + base.OnExit(); + Util.PlaySound(initialSoundString, base.gameObject); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform && NetworkServer.active) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.FindChild("LeftJet").gameObject.SetActive(value: false); + component.FindChild("RightJet").gameObject.SetActive(value: false); + if ((bool)initialEffect) + { + EffectManager.SpawnEffect(initialEffect, new EffectData + { + origin = base.transform.position, + scale = initialEffectScale + }, transmit: true); + } + } + } + Rigidbody component2 = GetComponent(); + RagdollController component3 = modelTransform.GetComponent(); + if ((bool)component3 && (bool)component2) + { + component3.BeginRagdoll(component2.velocity * velocityMagnitude); + } + ExplodeRigidbodiesOnStart component4 = modelTransform.GetComponent(); + if ((bool)component4) + { + component4.force = explosionForce; + component4.enabled = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/AimChainGun.cs b/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/AimChainGun.cs new file mode 100644 index 0000000..e64fced --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/AimChainGun.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates.DroneWeaponsChainGun; + +public class AimChainGun : BaseDroneWeaponChainGunState +{ + [SerializeField] + public float minDuration; + + [SerializeField] + public float maxEnemyDistanceToStartFiring; + + [SerializeField] + public float searchRefreshSeconds; + + private BullseyeSearch enemyFinder; + + private float searchRefreshTimer; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + enemyFinder = new BullseyeSearch(); + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + enemyFinder.maxDistanceFilter = maxEnemyDistanceToStartFiring; + enemyFinder.maxAngleFilter = float.MaxValue; + enemyFinder.filterByLoS = true; + enemyFinder.sortMode = BullseyeSearch.SortMode.Angle; + if ((bool)bodyTeamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(bodyTeamComponent.teamIndex); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority || !(base.fixedAge > minDuration)) + { + return; + } + searchRefreshTimer -= GetDeltaTime(); + if (!(searchRefreshTimer < 0f)) + { + return; + } + searchRefreshTimer = searchRefreshSeconds; + Ray aimRay = GetAimRay(); + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.RefreshCandidates(); + using IEnumerator enumerator = enemyFinder.GetResults().GetEnumerator(); + if (enumerator.MoveNext()) + { + HurtBox current = enumerator.Current; + outer.SetNextState(new FireChainGun(current)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/BaseDroneWeaponChainGunState.cs b/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/BaseDroneWeaponChainGunState.cs new file mode 100644 index 0000000..8aea3fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/BaseDroneWeaponChainGunState.cs @@ -0,0 +1,152 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates.DroneWeaponsChainGun; + +public abstract class BaseDroneWeaponChainGunState : EntityState +{ + private const string aimAnimatorChildName = "AimAnimator"; + + [SerializeField] + public float pitchRangeMin; + + [SerializeField] + public float pitchRangeMax; + + [SerializeField] + public float yawRangeMin; + + [SerializeField] + public float yawRangeMax; + + protected NetworkedBodyAttachment networkedBodyAttachment; + + protected GameObject bodyGameObject; + + protected CharacterBody body; + + protected List gunChildLocators; + + protected List gunAnimators; + + protected AimAnimator bodyAimAnimator; + + protected TeamComponent bodyTeamComponent; + + private bool linkedToDisplay; + + public override void OnEnter() + { + base.OnEnter(); + networkedBodyAttachment = GetComponent(); + if ((bool)networkedBodyAttachment) + { + bodyGameObject = networkedBodyAttachment.attachedBodyObject; + body = networkedBodyAttachment.attachedBody; + if ((bool)bodyGameObject && (bool)body) + { + ModelLocator component = body.GetComponent(); + if ((bool)component) + { + bodyAimAnimator = component.modelTransform.GetComponent(); + bodyTeamComponent = body.GetComponent(); + } + } + } + LinkToDisplay(); + } + + private void LinkToDisplay() + { + if (linkedToDisplay) + { + return; + } + gunAnimators = new List(); + gunChildLocators = new List(); + if (!networkedBodyAttachment) + { + return; + } + bodyGameObject = networkedBodyAttachment.attachedBodyObject; + body = networkedBodyAttachment.attachedBody; + if (!bodyGameObject || !body) + { + return; + } + ModelLocator component = body.GetComponent(); + if (!component || !component.modelTransform) + { + return; + } + bodyAimAnimator = component.modelTransform.GetComponent(); + bodyTeamComponent = body.GetComponent(); + CharacterModel component2 = component.modelTransform.GetComponent(); + if (!component2) + { + return; + } + List itemDisplayObjects = component2.GetItemDisplayObjects(DLC1Content.Items.DroneWeaponsDisplay1.itemIndex); + itemDisplayObjects.AddRange(component2.GetItemDisplayObjects(DLC1Content.Items.DroneWeaponsDisplay2.itemIndex)); + foreach (GameObject item in itemDisplayObjects) + { + ChildLocator component3 = item.GetComponent(); + if ((bool)component3) + { + gunChildLocators.Add(component3); + Animator animator = component3.FindChildComponent("AimAnimator"); + if ((bool)animator) + { + gunAnimators.Add(animator); + } + } + } + } + + public void PassDisplayLinks(List gunChildLocators, List gunAnimators) + { + if (!linkedToDisplay) + { + linkedToDisplay = true; + this.gunAnimators = gunAnimators; + this.gunChildLocators = gunChildLocators; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + LinkToDisplay(); + if (!bodyAimAnimator) + { + return; + } + foreach (Animator gunAnimator in gunAnimators) + { + bodyAimAnimator.UpdateAnimatorParameters(gunAnimator, pitchRangeMin, pitchRangeMax, yawRangeMin, yawRangeMax); + } + } + + protected Transform FindChild(string childName) + { + foreach (ChildLocator gunChildLocator in gunChildLocators) + { + Transform transform = gunChildLocator.FindChild(childName); + if ((bool)transform) + { + return transform; + } + } + return null; + } + + protected Ray GetAimRay() + { + if ((bool)body.inputBank) + { + return new Ray(body.inputBank.aimOrigin, body.inputBank.aimDirection); + } + return new Ray(base.transform.position, base.transform.forward); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/FireChainGun.cs b/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/FireChainGun.cs new file mode 100644 index 0000000..ff9880e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.DroneWeaponsChainGun/FireChainGun.cs @@ -0,0 +1,125 @@ +using RoR2; +using RoR2.Orbs; +using UnityEngine; + +namespace EntityStates.DroneWeaponsChainGun; + +public class FireChainGun : BaseDroneWeaponChainGunState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject orbEffectObject; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float orbSpeed; + + [SerializeField] + public int shotCount; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public int additionalBounces; + + [SerializeField] + public float bounceRange; + + [SerializeField] + public float damageCoefficientPerBounce; + + [SerializeField] + public int targetsToFindPerBounce; + + [SerializeField] + public bool canBounceOnSameTarget; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public string fireSoundString; + + private HurtBox targetHurtBox; + + private float duration; + + private int stepIndex; + + public FireChainGun() + { + } + + public FireChainGun(HurtBox targetHurtBox) + { + this.targetHurtBox = targetHurtBox; + } + + public override void OnEnter() + { + base.OnEnter(); + Transform transform = FindChild(muzzleName); + if (!transform) + { + transform = body.coreTransform; + } + if (base.isAuthority) + { + duration = baseDuration / body.attackSpeed; + ChainGunOrb chainGunOrb = new ChainGunOrb(orbEffectObject); + chainGunOrb.damageValue = body.damage * damageCoefficient; + chainGunOrb.isCrit = Util.CheckRoll(body.crit, body.master); + chainGunOrb.teamIndex = TeamComponent.GetObjectTeam(body.gameObject); + chainGunOrb.attacker = body.gameObject; + chainGunOrb.procCoefficient = procCoefficient; + chainGunOrb.procChainMask = default(ProcChainMask); + chainGunOrb.origin = transform.position; + chainGunOrb.target = targetHurtBox; + chainGunOrb.speed = orbSpeed; + chainGunOrb.bouncesRemaining = additionalBounces; + chainGunOrb.bounceRange = bounceRange; + chainGunOrb.damageCoefficientPerBounce = damageCoefficientPerBounce; + chainGunOrb.targetsToFindPerBounce = targetsToFindPerBounce; + chainGunOrb.canBounceOnSameTarget = canBounceOnSameTarget; + chainGunOrb.damageColorIndex = DamageColorIndex.Item; + OrbManager.instance.AddOrb(chainGunOrb); + } + if ((bool)transform) + { + EffectData effectData = new EffectData + { + origin = transform.position + }; + EffectManager.SpawnEffect(muzzleFlashPrefab, effectData, transmit: true); + } + Util.PlaySound(fireSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + BaseDroneWeaponChainGunState baseDroneWeaponChainGunState; + if (stepIndex < shotCount) + { + baseDroneWeaponChainGunState = new FireChainGun(targetHurtBox); + (baseDroneWeaponChainGunState as FireChainGun).stepIndex = stepIndex + 1; + } + else + { + baseDroneWeaponChainGunState = new AimChainGun(); + } + baseDroneWeaponChainGunState.PassDisplayLinks(gunChildLocators, gunAnimators); + outer.SetNextState(baseDroneWeaponChainGunState); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Duplicator/Duplicating.cs b/ilspy_dump/ror2_csproj/EntityStates.Duplicator/Duplicating.cs new file mode 100644 index 0000000..cdacd96 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Duplicator/Duplicating.cs @@ -0,0 +1,117 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Duplicator; + +public class Duplicating : BaseState +{ + public static float initialDelayDuration = 1f; + + public static float timeBetweenStartAndDropDroplet = 3f; + + public static string muzzleString; + + public static GameObject bakeEffectPrefab; + + public static GameObject releaseEffectPrefab; + + private GameObject bakeEffectInstance; + + private bool hasStartedCooking; + + private bool hasDroppedDroplet; + + private Transform muzzleTransform; + + private EffectManagerHelper _emh_bakeEffectInstance; + + private static int CookStateHash = Animator.StringToHash("Cook"); + + public override void Reset() + { + base.Reset(); + bakeEffectInstance = null; + hasStartedCooking = false; + hasDroppedDroplet = false; + muzzleTransform = null; + _emh_bakeEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild(muzzleString); + } + } + + private void BeginCooking() + { + if (hasStartedCooking) + { + return; + } + hasStartedCooking = true; + PlayAnimation("Body", CookStateHash); + if ((bool)base.sfxLocator) + { + Util.PlaySound(base.sfxLocator.openSound, base.gameObject); + } + if ((bool)muzzleTransform) + { + if (!EffectManager.ShouldUsePooledEffect(bakeEffectPrefab)) + { + bakeEffectInstance = Object.Instantiate(bakeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + return; + } + _emh_bakeEffectInstance = EffectManager.GetAndActivatePooledEffect(bakeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + bakeEffectInstance = _emh_bakeEffectInstance.gameObject; + } + } + + private void DropDroplet() + { + if (hasDroppedDroplet) + { + return; + } + hasDroppedDroplet = true; + GetComponent().DropPickup(); + if (!muzzleTransform) + { + return; + } + if ((bool)bakeEffectInstance) + { + if (_emh_bakeEffectInstance != null && _emh_bakeEffectInstance.OwningPool != null) + { + _emh_bakeEffectInstance.OwningPool.ReturnObject(_emh_bakeEffectInstance); + } + else + { + EntityState.Destroy(bakeEffectInstance); + } + _emh_bakeEffectInstance = null; + bakeEffectInstance = null; + } + if ((bool)releaseEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(releaseEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= initialDelayDuration) + { + BeginCooking(); + } + if (base.fixedAge >= initialDelayDuration + timeBetweenStartAndDropDroplet) + { + DropDroplet(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Emote/SurpriseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Emote/SurpriseState.cs new file mode 100644 index 0000000..a1cfdb8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Emote/SurpriseState.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace EntityStates.Emote; + +public class SurpriseState : EntityState +{ + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.Play("EmoteSurprise", layerIndex, 0f); + modelAnimator.Update(0f); + duration = modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).length; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiBubbleShield/Deployed.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiBubbleShield/Deployed.cs new file mode 100644 index 0000000..3103810 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiBubbleShield/Deployed.cs @@ -0,0 +1,62 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.EngiBubbleShield; + +public class Deployed : EntityState +{ + public static string childLocatorString; + + public static string initialSoundString; + + public static string destroySoundString; + + public static float delayToDeploy; + + public static float lifetime; + + [SerializeField] + public GameObject destroyEffectPrefab; + + [SerializeField] + public float destroyEffectRadius; + + private bool hasDeployed; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(initialSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!hasDeployed && base.fixedAge >= delayToDeploy) + { + ChildLocator component = GetComponent(); + if ((bool)component) + { + component.FindChild(childLocatorString).gameObject.SetActive(value: true); + hasDeployed = true; + } + } + if (base.fixedAge >= lifetime && NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + base.OnExit(); + EffectManager.SpawnEffect(destroyEffectPrefab, new EffectData + { + origin = base.transform.position, + rotation = base.transform.rotation, + scale = destroyEffectRadius + }, transmit: false); + Util.PlaySound(destroySoundString, base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiBubbleShield/Undeployed.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiBubbleShield/Undeployed.cs new file mode 100644 index 0000000..533b164 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiBubbleShield/Undeployed.cs @@ -0,0 +1,44 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine.Networking; + +namespace EntityStates.Engi.EngiBubbleShield; + +public class Undeployed : EntityState +{ + private ProjectileStickOnImpact projectileStickOnImpact; + + public override void OnEnter() + { + base.OnEnter(); + ProjectileController component = GetComponent(); + projectileStickOnImpact = GetComponent(); + if (!NetworkServer.active || !component.owner) + { + return; + } + CharacterBody component2 = component.owner.GetComponent(); + if ((bool)component2) + { + CharacterMaster master = component2.master; + if ((bool)master) + { + master.AddDeployable(GetComponent(), DeployableSlot.EngiBubbleShield); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (projectileStickOnImpact.stuck && NetworkServer.active) + { + SetNextState(); + } + } + + protected virtual void SetNextState() + { + outer.SetNextState(new Deployed()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/BaseEngiMissilePainterState.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/BaseEngiMissilePainterState.cs new file mode 100644 index 0000000..9c25ac3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/BaseEngiMissilePainterState.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Engi.EngiMissilePainter; + +public class BaseEngiMissilePainterState : BaseSkillState +{ + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Finish.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Finish.cs new file mode 100644 index 0000000..ae77987 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Finish.cs @@ -0,0 +1,13 @@ +namespace EntityStates.Engi.EngiMissilePainter; + +public class Finish : BaseEngiMissilePainterState +{ + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + outer.SetNextState(new Idle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Fire.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Fire.cs new file mode 100644 index 0000000..ab2e22f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Fire.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates.Engi.EngiMissilePainter; + +public class Fire : BaseEngiMissilePainterState +{ + public static float baseDurationPerMissile; + + public static float damageCoefficient; + + public static GameObject projectilePrefab; + + public static GameObject muzzleflashEffectPrefab; + + public List targetsList; + + private int fireIndex; + + private float durationPerMissile; + + private float stopwatch; + + private static int IdleHarpoonsStateHash = Animator.StringToHash("IdleHarpoons"); + + private static int FireHarpoonStateHash = Animator.StringToHash("FireHarpoon"); + + public override void OnEnter() + { + base.OnEnter(); + durationPerMissile = baseDurationPerMissile / attackSpeedStat; + PlayAnimation("Gesture, Additive", IdleHarpoonsStateHash); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + bool flag = false; + if (base.isAuthority) + { + stopwatch += GetDeltaTime(); + if (stopwatch >= durationPerMissile) + { + stopwatch -= durationPerMissile; + while (fireIndex < targetsList.Count) + { + HurtBox hurtBox = targetsList[fireIndex++]; + if (!hurtBox.healthComponent || !hurtBox.healthComponent.alive) + { + base.activatorSkillSlot.AddOneStock(); + continue; + } + string text = ((fireIndex % 2 == 0) ? "MuzzleLeft" : "MuzzleRight"); + Vector3 position = base.inputBank.aimOrigin; + Transform transform = FindModelChild(text); + if (transform != null) + { + position = transform.position; + } + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, text, transmit: true); + FireMissile(hurtBox, position); + flag = true; + break; + } + if (fireIndex >= targetsList.Count) + { + outer.SetNextState(new Finish()); + } + } + } + if (flag) + { + PlayAnimation((fireIndex % 2 == 0) ? "Gesture Left Cannon, Additive" : "Gesture Right Cannon, Additive", FireHarpoonStateHash); + } + } + + private void FireMissile(HurtBox target, Vector3 position) + { + MissileUtils.FireMissile(base.inputBank.aimOrigin, base.characterBody, default(ProcChainMask), target.gameObject, damageStat * damageCoefficient, RollCrit(), projectilePrefab, DamageColorIndex.Default, Vector3.up, 0f, addMissileProc: false); + } + + public override void OnExit() + { + base.OnExit(); + PlayCrossfade("Gesture, Additive", "ExitHarpoons", 0.1f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Paint.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Paint.cs new file mode 100644 index 0000000..3f614b9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Paint.cs @@ -0,0 +1,296 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Engi.EngiMissilePainter; + +public class Paint : BaseEngiMissilePainterState +{ + private struct IndicatorInfo + { + public int refCount; + + public EngiMissileIndicator indicator; + } + + private class EngiMissileIndicator : Indicator + { + public int missileCount; + + public override void UpdateVisualizer() + { + base.UpdateVisualizer(); + Transform transform = base.visualizerTransform.Find("DotOrigin"); + for (int num = transform.childCount - 1; num >= missileCount; num--) + { + EntityState.Destroy(transform.GetChild(num)); + } + for (int i = transform.childCount; i < missileCount; i++) + { + GameObject gameObject = Object.Instantiate(base.visualizerPrefab.transform.Find("DotOrigin/DotTemplate").gameObject, transform); + FindRenderers(gameObject.transform); + } + if (transform.childCount > 0) + { + float num2 = 360f / (float)transform.childCount; + float num3 = (float)(transform.childCount - 1) * 90f; + for (int j = 0; j < transform.childCount; j++) + { + Transform child = transform.GetChild(j); + child.gameObject.SetActive(value: true); + child.localRotation = Quaternion.Euler(0f, 0f, num3 + (float)j * num2); + } + } + } + + public EngiMissileIndicator(GameObject owner, GameObject visualizerPrefab) + : base(owner, visualizerPrefab) + { + } + } + + public static GameObject crosshairOverridePrefab; + + public static GameObject stickyTargetIndicatorPrefab; + + public static float stackInterval; + + public static string enterSoundString; + + public static string exitSoundString; + + public static string loopSoundString; + + public static string lockOnSoundString; + + public static string stopLoopSoundString; + + public static float maxAngle; + + public static float maxDistance; + + private List targetsList; + + private Dictionary targetIndicators; + + private Indicator stickyTargetIndicator; + + private SkillDef engiConfirmTargetDummySkillDef; + + private SkillDef engiCancelTargetingDummySkillDef; + + private bool releasedKeyOnce; + + private float stackStopwatch; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private BullseyeSearch search; + + private bool queuedFiringState; + + private uint loopSoundID; + + private HealthComponent previousHighlightTargetHealthComponent; + + private HurtBox previousHighlightTargetHurtBox; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + targetsList = new List(); + targetIndicators = new Dictionary(); + stickyTargetIndicator = new Indicator(base.gameObject, stickyTargetIndicatorPrefab); + search = new BullseyeSearch(); + } + PlayCrossfade("Gesture, Additive", "PrepHarpoons", 0.1f); + Util.PlaySound(enterSoundString, base.gameObject); + loopSoundID = Util.PlaySound(loopSoundString, base.gameObject); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + engiConfirmTargetDummySkillDef = SkillCatalog.GetSkillDef(SkillCatalog.FindSkillIndexByName("EngiConfirmTargetDummy")); + engiCancelTargetingDummySkillDef = SkillCatalog.GetSkillDef(SkillCatalog.FindSkillIndexByName("EngiCancelTargetingDummy")); + base.skillLocator.primary.SetSkillOverride(this, engiConfirmTargetDummySkillDef, GenericSkill.SkillOverridePriority.Contextual); + base.skillLocator.secondary.SetSkillOverride(this, engiCancelTargetingDummySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + + public override void OnExit() + { + if (base.isAuthority && !outer.destroying && !queuedFiringState) + { + for (int i = 0; i < targetsList.Count; i++) + { + base.activatorSkillSlot.AddOneStock(); + } + } + base.skillLocator.secondary.UnsetSkillOverride(this, engiCancelTargetingDummySkillDef, GenericSkill.SkillOverridePriority.Contextual); + base.skillLocator.primary.UnsetSkillOverride(this, engiConfirmTargetDummySkillDef, GenericSkill.SkillOverridePriority.Contextual); + if (targetIndicators != null) + { + foreach (KeyValuePair targetIndicator in targetIndicators) + { + targetIndicator.Value.indicator.active = false; + } + } + if (stickyTargetIndicator != null) + { + stickyTargetIndicator.active = false; + } + crosshairOverrideRequest?.Dispose(); + PlayCrossfade("Gesture, Additive", "ExitHarpoons", 0.1f); + Util.PlaySound(exitSoundString, base.gameObject); + Util.PlaySound(stopLoopSoundString, base.gameObject); + base.OnExit(); + } + + private void AddTargetAuthority(HurtBox hurtBox) + { + if (base.activatorSkillSlot.stock != 0) + { + Util.PlaySound(lockOnSoundString, base.gameObject); + targetsList.Add(hurtBox); + if (!targetIndicators.TryGetValue(hurtBox, out var value)) + { + IndicatorInfo indicatorInfo = default(IndicatorInfo); + indicatorInfo.refCount = 0; + indicatorInfo.indicator = new EngiMissileIndicator(base.gameObject, LegacyResourcesAPI.Load("Prefabs/EngiMissileTrackingIndicator")); + value = indicatorInfo; + value.indicator.targetTransform = hurtBox.transform; + value.indicator.active = true; + } + value.refCount++; + value.indicator.missileCount = value.refCount; + targetIndicators[hurtBox] = value; + base.activatorSkillSlot.DeductStock(1); + } + } + + private void RemoveTargetAtAuthority(int i) + { + HurtBox key = targetsList[i]; + targetsList.RemoveAt(i); + if (targetIndicators.TryGetValue(key, out var value)) + { + value.refCount--; + value.indicator.missileCount = value.refCount; + targetIndicators[key] = value; + if (value.refCount == 0) + { + value.indicator.active = false; + targetIndicators.Remove(key); + } + } + } + + private void CleanTargetsList() + { + for (int num = targetsList.Count - 1; num >= 0; num--) + { + HurtBox hurtBox = targetsList[num]; + if (!hurtBox.healthComponent || !hurtBox.healthComponent.alive) + { + RemoveTargetAtAuthority(num); + base.activatorSkillSlot.AddOneStock(); + } + } + for (int num2 = targetsList.Count - 1; num2 >= base.activatorSkillSlot.maxStock; num2--) + { + RemoveTargetAtAuthority(num2); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(3f); + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + private void GetCurrentTargetInfo(out HurtBox currentTargetHurtBox, out HealthComponent currentTargetHealthComponent) + { + Ray aimRay = GetAimRay(); + search.filterByDistinctEntity = true; + search.filterByLoS = true; + search.minDistanceFilter = 0f; + search.maxDistanceFilter = maxDistance; + search.minAngleFilter = 0f; + search.maxAngleFilter = maxAngle; + search.viewer = base.characterBody; + search.searchOrigin = aimRay.origin; + search.searchDirection = aimRay.direction; + search.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + search.teamMaskFilter = TeamMask.GetUnprotectedTeams(GetTeam()); + search.RefreshCandidates(); + search.FilterOutGameObject(base.gameObject); + foreach (HurtBox result in search.GetResults()) + { + if ((bool)result.healthComponent && result.healthComponent.alive) + { + currentTargetHurtBox = result; + currentTargetHealthComponent = result.healthComponent; + return; + } + } + currentTargetHurtBox = null; + currentTargetHealthComponent = null; + } + + private void AuthorityFixedUpdate() + { + CleanTargetsList(); + bool flag = false; + GetCurrentTargetInfo(out var currentTargetHurtBox, out var currentTargetHealthComponent); + if ((bool)currentTargetHurtBox) + { + stackStopwatch += GetDeltaTime(); + if (base.inputBank.skill1.down && (previousHighlightTargetHealthComponent != currentTargetHealthComponent || stackStopwatch > stackInterval / attackSpeedStat || base.inputBank.skill1.justPressed)) + { + stackStopwatch = 0f; + AddTargetAuthority(currentTargetHurtBox); + } + } + if (base.inputBank.skill1.justReleased) + { + flag = true; + } + if (base.inputBank.skill2.justReleased) + { + outer.SetNextStateToMain(); + return; + } + if (base.inputBank.skill3.justReleased) + { + if (releasedKeyOnce) + { + flag = true; + } + releasedKeyOnce = true; + } + if ((object)currentTargetHurtBox != previousHighlightTargetHurtBox) + { + previousHighlightTargetHurtBox = currentTargetHurtBox; + previousHighlightTargetHealthComponent = currentTargetHealthComponent; + stickyTargetIndicator.targetTransform = (((bool)currentTargetHurtBox && base.activatorSkillSlot.stock != 0) ? currentTargetHurtBox.transform : null); + stackStopwatch = 0f; + } + stickyTargetIndicator.active = stickyTargetIndicator.targetTransform; + if (flag) + { + queuedFiringState = true; + outer.SetNextState(new Fire + { + targetsList = targetsList, + activatorSkillSlot = base.activatorSkillSlot + }); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Startup.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Startup.cs new file mode 100644 index 0000000..dd8ba1e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiMissilePainter/Startup.cs @@ -0,0 +1,23 @@ +namespace EntityStates.Engi.EngiMissilePainter; + +public class Startup : BaseEngiMissilePainterState +{ + public static float baseDuration; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && duration <= base.fixedAge) + { + outer.SetNextState(new Paint()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWallShield/Deployed.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWallShield/Deployed.cs new file mode 100644 index 0000000..5254ce4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWallShield/Deployed.cs @@ -0,0 +1,7 @@ +using EntityStates.Engi.EngiBubbleShield; + +namespace EntityStates.Engi.EngiWallShield; + +public class Deployed : EntityStates.Engi.EngiBubbleShield.Deployed +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWallShield/Undeployed.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWallShield/Undeployed.cs new file mode 100644 index 0000000..655a129 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWallShield/Undeployed.cs @@ -0,0 +1,20 @@ +using EntityStates.Engi.EngiBubbleShield; +using UnityEngine; + +namespace EntityStates.Engi.EngiWallShield; + +public class Undeployed : EntityStates.Engi.EngiBubbleShield.Undeployed +{ + public override void OnEnter() + { + base.OnEnter(); + } + + protected override void SetNextState() + { + Vector3 forward = base.transform.forward; + Vector3 forward2 = new Vector3(forward.x, 0f, forward.z); + base.transform.forward = forward2; + outer.SetNextState(new Deployed()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/ChargeGrenades.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/ChargeGrenades.cs new file mode 100644 index 0000000..e7467fe --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/ChargeGrenades.cs @@ -0,0 +1,178 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Engi.EngiWeapon; + +public class ChargeGrenades : BaseState +{ + public static float baseTotalDuration; + + public static float baseMaxChargeTime; + + public static int maxCharges; + + public static GameObject chargeEffectPrefab; + + public static string chargeStockSoundString; + + public static string chargeLoopStartSoundString; + + public static string chargeLoopStopSoundString; + + public static int minGrenadeCount; + + public static int maxGrenadeCount; + + public static float minBonusBloom; + + public static float maxBonusBloom; + + private GameObject chargeLeftInstance; + + private GameObject chargeRightInstance; + + private int charge; + + private int lastCharge; + + private float totalDuration; + + private float maxChargeTime; + + private EffectManagerHelper _emh_chargeLeftInstance; + + private EffectManagerHelper _emh_chargeRightInstance; + + private static int ChargeGrenadesStateHash = Animator.StringToHash("ChargeGrenades"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + public override void Reset() + { + base.Reset(); + chargeLeftInstance = null; + chargeRightInstance = null; + charge = 0; + lastCharge = 0; + totalDuration = 0f; + maxChargeTime = 0f; + _emh_chargeLeftInstance = null; + _emh_chargeRightInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + totalDuration = baseTotalDuration / attackSpeedStat; + maxChargeTime = baseMaxChargeTime / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayAnimation("Gesture, Additive", ChargeGrenadesStateHash); + Util.PlaySound(chargeLoopStartSoundString, base.gameObject); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("MuzzleLeft"); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeLeftInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeLeftInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeLeftInstance = _emh_chargeLeftInstance.gameObject; + } + chargeLeftInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeLeftInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = totalDuration; + } + } + Transform transform2 = component.FindChild("MuzzleRight"); + if ((bool)transform2 && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeRightInstance = Object.Instantiate(chargeEffectPrefab, transform2.position, transform2.rotation); + } + else + { + _emh_chargeRightInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform2.position, transform2.rotation); + chargeRightInstance = _emh_chargeRightInstance.gameObject; + } + chargeRightInstance.transform.parent = transform2; + ScaleParticleSystemDuration component3 = chargeRightInstance.GetComponent(); + if ((bool)component3) + { + component3.newDuration = totalDuration; + } + } + } + + public override void OnExit() + { + base.OnExit(); + PlayAnimation("Gesture, Additive", EmptyStateHash); + Util.PlaySound(chargeLoopStopSoundString, base.gameObject); + if (chargeLeftInstance != null) + { + if (_emh_chargeLeftInstance != null && _emh_chargeLeftInstance.OwningPool != null) + { + _emh_chargeLeftInstance.OwningPool.ReturnObject(_emh_chargeLeftInstance); + } + else + { + EntityState.Destroy(chargeLeftInstance); + } + chargeLeftInstance = null; + _emh_chargeLeftInstance = null; + } + if (chargeRightInstance != null) + { + if (_emh_chargeRightInstance != null && _emh_chargeRightInstance.OwningPool != null) + { + _emh_chargeRightInstance.OwningPool.ReturnObject(_emh_chargeRightInstance); + } + else + { + EntityState.Destroy(chargeRightInstance); + } + chargeRightInstance = null; + _emh_chargeRightInstance = null; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + lastCharge = charge; + charge = Mathf.Min((int)(base.fixedAge / maxChargeTime * (float)maxCharges), maxCharges); + float t = (float)charge / (float)maxCharges; + float value = Mathf.Lerp(minBonusBloom, maxBonusBloom, t); + base.characterBody.SetSpreadBloom(value); + int num = Mathf.FloorToInt(Mathf.Lerp(minGrenadeCount, maxGrenadeCount, t)); + if (lastCharge < charge) + { + Util.PlaySound(chargeStockSoundString, base.gameObject, "engiM1_chargePercent", 100f * ((float)(num - 1) / (float)maxGrenadeCount)); + } + if ((base.fixedAge >= totalDuration || !base.inputBank || !base.inputBank.skill1.down) && base.isAuthority) + { + FireGrenades fireGrenades = new FireGrenades(); + fireGrenades.grenadeCountMax = num; + outer.SetNextState(fireGrenades); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiOtherShield.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiOtherShield.cs new file mode 100644 index 0000000..91f7860 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiOtherShield.cs @@ -0,0 +1,84 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.EngiWeapon; + +public class EngiOtherShield : BaseState +{ + public CharacterBody target; + + public float minimumDuration; + + private Indicator indicator; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)target) + { + indicator = new Indicator(base.gameObject, LegacyResourcesAPI.Load("Prefabs/EngiShieldRetractIndicator")); + indicator.active = true; + indicator.targetTransform = Util.GetCoreTransform(target.gameObject); + target.AddBuff(RoR2Content.Buffs.EngiShield); + target.RecalculateStats(); + HealthComponent component = target.GetComponent(); + if ((bool)component) + { + component.RechargeShieldFull(); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!target || !base.characterBody.healthComponent.alive) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.skillLocator.utility = base.skillLocator.FindSkill("GiveShield"); + if (NetworkServer.active && (bool)target) + { + target.RemoveBuff(RoR2Content.Buffs.EngiShield); + } + if (base.isAuthority) + { + base.skillLocator.utility.RemoveAllStocks(); + } + if (indicator != null) + { + indicator.active = false; + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge >= minimumDuration)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(target.gameObject); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + GameObject gameObject = reader.ReadGameObject(); + if ((bool)gameObject) + { + target = gameObject.GetComponent(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiSelfShield.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiSelfShield.cs new file mode 100644 index 0000000..9794f2f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiSelfShield.cs @@ -0,0 +1,99 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.EngiWeapon; + +public class EngiSelfShield : BaseState +{ + public static float transferDelay = 0.1f; + + private HurtBox transferTarget; + + private BullseyeSearch friendLocator; + + private Indicator indicator; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.AddBuff(RoR2Content.Buffs.EngiShield); + base.characterBody.RecalculateStats(); + if ((bool)base.healthComponent) + { + base.healthComponent.RechargeShieldFull(); + } + } + friendLocator = new BullseyeSearch(); + friendLocator.teamMaskFilter = TeamMask.none; + if ((bool)base.teamComponent) + { + friendLocator.teamMaskFilter.AddTeam(base.teamComponent.teamIndex); + } + friendLocator.maxDistanceFilter = 80f; + friendLocator.maxAngleFilter = 20f; + friendLocator.sortMode = BullseyeSearch.SortMode.Angle; + friendLocator.filterByLoS = false; + indicator = new Indicator(base.gameObject, LegacyResourcesAPI.Load("Prefabs/ShieldTransferIndicator")); + } + + public override void OnExit() + { + base.skillLocator.utility = base.skillLocator.FindSkill("RetractShield"); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.EngiShield); + } + if (base.isAuthority) + { + base.skillLocator.utility.RemoveAllStocks(); + } + indicator.active = false; + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority || !(base.fixedAge >= transferDelay) || !base.skillLocator.utility.IsReady()) + { + return; + } + if ((bool)base.characterBody) + { + float extraRaycastDistance = 0f; + Ray ray = CameraRigController.ModifyAimRayIfApplicable(GetAimRay(), base.gameObject, out extraRaycastDistance); + friendLocator.searchOrigin = ray.origin; + friendLocator.searchDirection = ray.direction; + friendLocator.maxDistanceFilter += extraRaycastDistance; + friendLocator.RefreshCandidates(); + friendLocator.FilterOutGameObject(base.gameObject); + transferTarget = friendLocator.GetResults().FirstOrDefault(); + } + HealthComponent healthComponent = (transferTarget ? transferTarget.healthComponent : null); + if ((bool)healthComponent) + { + indicator.targetTransform = Util.GetCoreTransform(healthComponent.gameObject); + if ((bool)base.inputBank && base.inputBank.skill3.justPressed) + { + EngiOtherShield engiOtherShield = new EngiOtherShield(); + engiOtherShield.target = healthComponent.gameObject.GetComponent(); + outer.SetNextState(engiOtherShield); + return; + } + } + else + { + indicator.targetTransform = null; + } + indicator.active = indicator.targetTransform; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiTeamShield.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiTeamShield.cs new file mode 100644 index 0000000..ee52ddb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/EngiTeamShield.cs @@ -0,0 +1,57 @@ +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.EngiWeapon; + +public class EngiTeamShield : BaseState +{ + public static float duration = 3f; + + public static float radius; + + public override void OnEnter() + { + base.OnEnter(); + if (!base.teamComponent || !NetworkServer.active) + { + return; + } + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(base.teamComponent.teamIndex); + float num = radius * radius; + Vector3 position = base.transform.position; + for (int i = 0; i < teamMembers.Count; i++) + { + if (!((teamMembers[i].transform.position - position).sqrMagnitude <= num)) + { + continue; + } + CharacterBody component = teamMembers[i].GetComponent(); + if ((bool)component) + { + component.AddTimedBuff(JunkContent.Buffs.EngiTeamShield, duration); + HealthComponent component2 = component.GetComponent(); + if ((bool)component2) + { + component2.RechargeShieldFull(); + } + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireBubbleShield.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireBubbleShield.cs new file mode 100644 index 0000000..9f5ebd1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireBubbleShield.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.EngiWeapon; + +public class FireBubbleShield : FireMines +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireConcussionBlast.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireConcussionBlast.cs new file mode 100644 index 0000000..43c9044 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireConcussionBlast.cs @@ -0,0 +1,137 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Engi.EngiWeapon; + +public class FireConcussionBlast : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static int grenadeCountMax = 3; + + public static float damageCoefficient; + + public static float fireDuration = 1f; + + public static float baseDuration = 2f; + + public static float minSpread = 0f; + + public static float maxSpread = 5f; + + public static float recoilAmplitude = 1f; + + public static string attackSoundString; + + public static float force; + + public static float maxDistance; + + public static float radius; + + public static GameObject tracerEffectPrefab; + + private Ray aimRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private void FireGrenade(string targetMuzzle) + { + Util.PlaySound(attackSoundString, base.gameObject); + aimRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + aimRay.origin = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.maxDistance = maxDistance; + bulletAttack.radius = radius; + bulletAttack.stopperMask = 0; + bulletAttack.Fire(); + } + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + aimRay = GetAimRay(); + StartAimMode(aimRay); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + fireTimer -= GetDeltaTime(); + float num = fireDuration / attackSpeedStat / (float)grenadeCountMax; + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + fireTimer += num; + if (grenadeCount % 2 == 0) + { + FireGrenade("MuzzleLeft"); + PlayCrossfade("Gesture, Left Cannon", "FireGrenadeLeft", 0.1f); + } + else + { + FireGrenade("MuzzleRight"); + PlayCrossfade("Gesture, Right Cannon", "FireGrenadeRight", 0.1f); + } + grenadeCount++; + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireGrenades.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireGrenades.cs new file mode 100644 index 0000000..900f8c9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireGrenades.cs @@ -0,0 +1,120 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Engi.EngiWeapon; + +public class FireGrenades : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public int grenadeCountMax = 3; + + public static float damageCoefficient; + + public static float fireDuration = 1f; + + public static float baseDuration = 2f; + + public static float arcAngle = 5f; + + public static float recoilAmplitude = 1f; + + public static string attackSoundString; + + public static float spreadBloomValue = 0.3f; + + private Ray projectileRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private void FireGrenade(string targetMuzzle) + { + Util.PlaySound(attackSoundString, base.gameObject); + projectileRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + projectileRay.origin = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + float x = Random.Range(0f, base.characterBody.spreadBloomAngle); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, projectileRay.direction); + Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y = vector.y; + vector.y = 0f; + float angle = Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f + arcAngle; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * projectileRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, projectileRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + StartAimMode(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + float num = fireDuration / attackSpeedStat / (float)grenadeCountMax; + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + fireTimer += num; + if (grenadeCount % 2 == 0) + { + FireGrenade("MuzzleLeft"); + PlayCrossfade("Gesture Left Cannon, Additive", "FireGrenadeLeft", 0.1f); + } + else + { + FireGrenade("MuzzleRight"); + PlayCrossfade("Gesture Right Cannon, Additive", "FireGrenadeRight", 0.1f); + } + grenadeCount++; + } + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireMines.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireMines.cs new file mode 100644 index 0000000..361a9a3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireMines.cs @@ -0,0 +1,69 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Engi.EngiWeapon; + +public class FireMines : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + public static float baseDuration = 2f; + + public static string throwMineSoundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(throwMineSoundString, base.gameObject); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + if ((bool)GetModelAnimator()) + { + float num = duration * 0.3f; + PlayCrossfade("Gesture, Additive", "FireMineRight", "FireMine.playbackRate", duration + num, 0.05f); + } + string muzzleName = "MuzzleCenter"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireSeekerGrenades.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireSeekerGrenades.cs new file mode 100644 index 0000000..a045e13 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireSeekerGrenades.cs @@ -0,0 +1,128 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Engi.EngiWeapon; + +public class FireSeekerGrenades : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject projectilePrefab; + + public static int grenadeCountMax = 3; + + public static float damageCoefficient; + + public static float fireDuration = 1f; + + public static float baseDuration = 2f; + + public static float minSpread = 0f; + + public static float maxSpread = 5f; + + public static float arcAngle = 5f; + + public static float recoilAmplitude = 1f; + + public static string attackSoundString; + + private Ray aimRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private void FireGrenade(string targetMuzzle) + { + Util.PlaySound(attackSoundString, base.gameObject); + aimRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + aimRay.origin = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + float x = Random.Range(minSpread, maxSpread); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, aimRay.direction); + Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y = vector.y; + vector.y = 0f; + float angle = Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f + arcAngle; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * aimRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + aimRay = GetAimRay(); + StartAimMode(aimRay); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + fireTimer -= GetDeltaTime(); + float num = fireDuration / attackSpeedStat / (float)grenadeCountMax; + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + fireTimer += num; + if (grenadeCount % 2 == 0) + { + FireGrenade("MuzzleLeft"); + PlayCrossfade("Gesture, Left Cannon", "FireGrenadeLeft", 0.1f); + } + else + { + FireGrenade("MuzzleRight"); + PlayCrossfade("Gesture, Right Cannon", "FireGrenadeRight", 0.1f); + } + grenadeCount++; + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireSpiderMine.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireSpiderMine.cs new file mode 100644 index 0000000..fbfc404 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireSpiderMine.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.EngiWeapon; + +public class FireSpiderMine : FireMines +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireWallShield.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireWallShield.cs new file mode 100644 index 0000000..9760ecb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/FireWallShield.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.EngiWeapon; + +public class FireWallShield : FireMines +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/PlaceTurret.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/PlaceTurret.cs new file mode 100644 index 0000000..2f9ada4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/PlaceTurret.cs @@ -0,0 +1,203 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Engi.EngiWeapon; + +public class PlaceTurret : BaseState +{ + private struct PlacementInfo + { + public bool ok; + + public Vector3 position; + + public Quaternion rotation; + } + + [SerializeField] + public GameObject wristDisplayPrefab; + + [SerializeField] + public string placeSoundString; + + [SerializeField] + public GameObject blueprintPrefab; + + [SerializeField] + public GameObject turretMasterPrefab; + + private const float placementMaxUp = 1f; + + private const float placementMaxDown = 3f; + + private const float placementForwardDistance = 2f; + + private const float entryDelay = 0.1f; + + private const float exitDelay = 0.25f; + + private const float turretRadius = 0.5f; + + private const float turretHeight = 1.82f; + + private const float turretCenter = 0f; + + private const float turretModelYOffset = -0.75f; + + private GameObject wristDisplayObject; + + private BlueprintController blueprints; + + private float exitCountdown; + + private bool exitPending; + + private float entryCountdown; + + private static int PrepTurretStateHash = Animator.StringToHash("PrepTurret"); + + private static int PlaceTurretStateHash = Animator.StringToHash("PlaceTurret"); + + private PlacementInfo currentPlacementInfo; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + currentPlacementInfo = GetPlacementInfo(); + blueprints = Object.Instantiate(blueprintPrefab, currentPlacementInfo.position, currentPlacementInfo.rotation).GetComponent(); + } + PlayAnimation("Gesture", PrepTurretStateHash); + entryCountdown = 0.1f; + exitCountdown = 0.25f; + exitPending = false; + if (!base.modelLocator) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("WristDisplay"); + if ((bool)transform) + { + wristDisplayObject = Object.Instantiate(wristDisplayPrefab, transform); + } + } + } + + private PlacementInfo GetPlacementInfo() + { + Ray aimRay = GetAimRay(); + Vector3 direction = aimRay.direction; + direction.y = 0f; + direction.Normalize(); + aimRay.direction = direction; + PlacementInfo result = default(PlacementInfo); + result.ok = false; + result.rotation = Util.QuaternionSafeLookRotation(-direction); + Ray ray = new Ray(aimRay.GetPoint(2f) + Vector3.up * 1f, Vector3.down); + float num = 4f; + float num2 = num; + if (Physics.SphereCast(ray, 0.5f, out var hitInfo, num, LayerIndex.world.mask) && hitInfo.normal.y > 0.5f) + { + num2 = hitInfo.distance; + result.ok = true; + } + Vector3 point = ray.GetPoint(num2 + 0.5f); + result.position = point; + if (result.ok) + { + float num3 = Mathf.Max(1.82f, 0f); + if (Physics.CheckCapsule(result.position + Vector3.up * (num3 - 0.5f), result.position + Vector3.up * 0.5f, 0.45f, (int)LayerIndex.world.mask | (int)LayerIndex.CommonMasks.characterBodiesOrDefault)) + { + result.ok = false; + } + } + return result; + } + + private void DestroyBlueprints() + { + if ((bool)blueprints) + { + EntityState.Destroy(blueprints.gameObject); + blueprints = null; + } + } + + public override void OnExit() + { + base.OnExit(); + PlayAnimation("Gesture", PlaceTurretStateHash); + if ((bool)wristDisplayObject) + { + EntityState.Destroy(wristDisplayObject); + } + DestroyBlueprints(); + } + + public override void Update() + { + base.Update(); + currentPlacementInfo = GetPlacementInfo(); + if ((bool)blueprints) + { + blueprints.PushState(currentPlacementInfo.position, currentPlacementInfo.rotation, currentPlacementInfo.ok); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + entryCountdown -= GetDeltaTime(); + if (exitPending) + { + exitCountdown -= GetDeltaTime(); + if (exitCountdown <= 0f) + { + outer.SetNextStateToMain(); + } + } + else + { + if (!base.inputBank || !(entryCountdown <= 0f)) + { + return; + } + if ((base.inputBank.skill1.down || base.inputBank.skill4.justPressed) && currentPlacementInfo.ok) + { + if ((bool)base.characterBody) + { + base.characterBody.SendConstructTurret(base.characterBody, currentPlacementInfo.position, currentPlacementInfo.rotation, MasterCatalog.FindMasterIndex(turretMasterPrefab)); + if ((bool)base.skillLocator) + { + GenericSkill skill = base.skillLocator.GetSkill(SkillSlot.Special); + if ((bool)skill) + { + skill.DeductStock(1); + } + } + } + Util.PlaySound(placeSoundString, base.gameObject); + DestroyBlueprints(); + exitPending = true; + } + if (base.inputBank.skill2.justPressed) + { + DestroyBlueprints(); + exitPending = true; + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/PlaceWalkerTurret.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/PlaceWalkerTurret.cs new file mode 100644 index 0000000..423bd65 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/PlaceWalkerTurret.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.EngiWeapon; + +public class PlaceWalkerTurret : PlaceTurret +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/ThrowMineDeployer.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/ThrowMineDeployer.cs new file mode 100644 index 0000000..d9e7d4f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.EngiWeapon/ThrowMineDeployer.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.EngiWeapon; + +public class ThrowMineDeployer : AimThrowableBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/Arm.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/Arm.cs new file mode 100644 index 0000000..fb28120 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/Arm.cs @@ -0,0 +1,19 @@ +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class Arm : BaseMineState +{ + public static float duration; + + protected override bool shouldStick => true; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && duration <= base.fixedAge) + { + outer.SetNextState(new WaitForTarget()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/BaseMineArmingState.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/BaseMineArmingState.cs new file mode 100644 index 0000000..b1b9951 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/BaseMineArmingState.cs @@ -0,0 +1,53 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Engi.Mine; + +public class BaseMineArmingState : BaseState +{ + [SerializeField] + public float damageScale; + + [SerializeField] + public float forceScale; + + [SerializeField] + public float blastRadiusScale; + + [SerializeField] + public float triggerRadius; + + [SerializeField] + public string onEnterSfx; + + [SerializeField] + public float onEnterSfxPlaybackRate; + + [SerializeField] + public string pathToChildToEnable; + + private Transform enabledChild; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlayAttackSpeedSound(onEnterSfx, base.gameObject, onEnterSfxPlaybackRate); + if (!string.IsNullOrEmpty(pathToChildToEnable)) + { + enabledChild = base.transform.Find(pathToChildToEnable); + if ((bool)enabledChild) + { + enabledChild.gameObject.SetActive(value: true); + } + } + } + + public override void OnExit() + { + if ((bool)enabledChild) + { + enabledChild.gameObject.SetActive(value: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/BaseMineState.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/BaseMineState.cs new file mode 100644 index 0000000..1ce9101 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/BaseMineState.cs @@ -0,0 +1,41 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class BaseMineState : BaseState +{ + [SerializeField] + public string enterSoundString; + + protected ProjectileStickOnImpact projectileStickOnImpact { get; private set; } + + protected EntityStateMachine armingStateMachine { get; private set; } + + protected virtual bool shouldStick => false; + + protected virtual bool shouldRevertToWaitForStickOnSurfaceLost => false; + + public override void OnEnter() + { + base.OnEnter(); + projectileStickOnImpact = GetComponent(); + armingStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Arming"); + if (projectileStickOnImpact.enabled != shouldStick) + { + projectileStickOnImpact.enabled = shouldStick; + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && shouldRevertToWaitForStickOnSurfaceLost && !projectileStickOnImpact.stuck) + { + outer.SetNextState(new WaitForStick()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/Detonate.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/Detonate.cs new file mode 100644 index 0000000..875ffd2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/Detonate.cs @@ -0,0 +1,66 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class Detonate : BaseMineState +{ + public static float blastRadius; + + public static GameObject explosionEffectPrefab; + + protected override bool shouldStick => false; + + protected override bool shouldRevertToWaitForStickOnSurfaceLost => false; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + Explode(); + } + } + + private void Explode() + { + ProjectileDamage component = GetComponent(); + float num = 0f; + float num2 = 0f; + float num3 = 0f; + if (base.armingStateMachine?.state is BaseMineArmingState baseMineArmingState) + { + num = baseMineArmingState.damageScale; + num2 = baseMineArmingState.forceScale; + num3 = baseMineArmingState.blastRadiusScale; + } + float num4 = blastRadius * num3; + BlastAttack blastAttack = new BlastAttack(); + blastAttack.procChainMask = base.projectileController.procChainMask; + blastAttack.procCoefficient = base.projectileController.procCoefficient; + blastAttack.attacker = base.projectileController.owner; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = base.projectileController.teamFilter.teamIndex; + blastAttack.procCoefficient = base.projectileController.procCoefficient; + blastAttack.baseDamage = component.damage * num; + blastAttack.baseForce = component.force * num2; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.crit = component.crit; + blastAttack.radius = num4; + blastAttack.position = base.transform.position; + blastAttack.damageColorIndex = component.damageColorIndex; + blastAttack.Fire(); + if ((bool)explosionEffectPrefab) + { + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = base.transform.position, + rotation = base.transform.rotation, + scale = num4 + }, transmit: true); + } + EntityState.Destroy(base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingFull.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingFull.cs new file mode 100644 index 0000000..94fa49d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingFull.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.Mine; + +public class MineArmingFull : BaseMineArmingState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingUnarmed.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingUnarmed.cs new file mode 100644 index 0000000..f3f9962 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingUnarmed.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Engi.Mine; + +public class MineArmingUnarmed : BaseMineArmingState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingWeak.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingWeak.cs new file mode 100644 index 0000000..ebd8ba9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/MineArmingWeak.cs @@ -0,0 +1,17 @@ +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class MineArmingWeak : BaseMineArmingState +{ + public static float duration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && duration <= base.fixedAge) + { + outer.SetNextState(new MineArmingFull()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/PreDetonate.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/PreDetonate.cs new file mode 100644 index 0000000..58641d6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/PreDetonate.cs @@ -0,0 +1,34 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class PreDetonate : BaseMineState +{ + public static float duration; + + public static string pathToPrepForExplosionChildEffect; + + public static float detachForce; + + protected override bool shouldStick => false; + + protected override bool shouldRevertToWaitForStickOnSurfaceLost => false; + + public override void OnEnter() + { + base.OnEnter(); + base.transform.Find(pathToPrepForExplosionChildEffect).gameObject.SetActive(value: true); + base.rigidbody.AddForce(base.transform.forward * detachForce); + base.rigidbody.AddTorque(Random.onUnitSphere * 200f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && duration <= base.fixedAge) + { + outer.SetNextState(new Detonate()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/WaitForStick.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/WaitForStick.cs new file mode 100644 index 0000000..31bba9b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/WaitForStick.cs @@ -0,0 +1,28 @@ +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class WaitForStick : BaseMineState +{ + protected override bool shouldStick => true; + + protected override bool shouldRevertToWaitForStickOnSurfaceLost => false; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + base.armingStateMachine.SetNextState(new MineArmingUnarmed()); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.projectileStickOnImpact.stuck) + { + outer.SetNextState(new Arm()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/WaitForTarget.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/WaitForTarget.cs new file mode 100644 index 0000000..468acbc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.Mine/WaitForTarget.cs @@ -0,0 +1,53 @@ +using RoR2.Projectile; +using UnityEngine.Networking; + +namespace EntityStates.Engi.Mine; + +public class WaitForTarget : BaseMineState +{ + private ProjectileSphereTargetFinder targetFinder; + + private ProjectileTargetComponent projectileTargetComponent; + + private ProjectileImpactExplosion projectileImpactExplosion; + + protected override bool shouldStick => true; + + public override void OnEnter() + { + base.OnEnter(); + projectileTargetComponent = GetComponent(); + targetFinder = GetComponent(); + if (NetworkServer.active) + { + targetFinder.enabled = true; + base.armingStateMachine.SetNextState(new MineArmingWeak()); + } + } + + public override void OnExit() + { + if ((bool)targetFinder) + { + targetFinder.enabled = false; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)targetFinder) + { + if ((bool)projectileTargetComponent.target) + { + outer.SetNextState(new PreDetonate()); + } + if (base.armingStateMachine?.state is BaseMineArmingState baseMineArmingState) + { + targetFinder.enabled = baseMineArmingState.triggerRadius != 0f; + targetFinder.lookRange = baseMineArmingState.triggerRadius; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/BaseMineDeployerState.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/BaseMineDeployerState.cs new file mode 100644 index 0000000..6f432c5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/BaseMineDeployerState.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace EntityStates.Engi.MineDeployer; + +public class BaseMineDeployerState : BaseState +{ + public static List instancesList = new List(); + + public GameObject owner { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + owner = base.projectileController?.owner; + instancesList.Add(this); + } + + public override void OnExit() + { + instancesList.Remove(this); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/FireMine.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/FireMine.cs new file mode 100644 index 0000000..cf75374 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/FireMine.cs @@ -0,0 +1,156 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Engi.MineDeployer; + +public class FireMine : BaseMineDeployerState +{ + public static float duration; + + public static float launchApex; + + public static float patternRadius; + + public static GameObject projectilePrefab; + + private int fireIndex; + + private static Vector3[] velocities; + + private static bool velocitiesResolved; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + ResolveVelocities(); + Transform transform = base.transform.Find("FirePoint"); + ProjectileDamage component = GetComponent(); + Vector3 forward = transform.TransformVector(velocities[fireIndex]); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.crit = component.crit; + fireProjectileInfo.damage = component.damage; + fireProjectileInfo.damageColorIndex = component.damageColorIndex; + fireProjectileInfo.force = component.force; + fireProjectileInfo.owner = base.owner; + fireProjectileInfo.position = transform.position; + fireProjectileInfo.procChainMask = base.projectileController.procChainMask; + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.rotation = Quaternion.LookRotation(forward); + fireProjectileInfo.fuseOverride = -1f; + fireProjectileInfo.useFuseOverride = false; + fireProjectileInfo.speedOverride = forward.magnitude; + fireProjectileInfo.useSpeedOverride = true; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && duration <= base.fixedAge) + { + int num = fireIndex + 1; + if (num < velocities.Length) + { + outer.SetNextState(new FireMine + { + fireIndex = num + }); + } + else + { + outer.SetNextState(new WaitForDeath()); + } + } + } + + private static Vector3[] GeneratePoints(float radius) + { + Vector3[] array = new Vector3[9]; + Quaternion quaternion = Quaternion.AngleAxis(60f, Vector3.up); + Quaternion quaternion2 = Quaternion.AngleAxis(120f, Vector3.up); + Vector3 forward = Vector3.forward; + array[0] = forward; + array[1] = quaternion2 * array[0]; + array[2] = quaternion2 * array[1]; + float num = 1f; + float num2 = Vector3.Distance(array[0], array[1]); + float num3 = Mathf.Sqrt(num * num + num2 * num2) / num; + array[3] = quaternion * (array[2] * num3); + array[4] = quaternion2 * array[3]; + array[5] = quaternion2 * array[4]; + num3 = 1f; + array[6] = quaternion * (array[5] * num3); + array[7] = quaternion2 * array[6]; + array[8] = quaternion2 * array[7]; + float num4 = radius / array[8].magnitude; + for (int i = 0; i < array.Length; i++) + { + array[i] *= num4; + } + return array; + } + + private static Vector3[] GenerateHexPoints(float radius) + { + Vector3[] array = new Vector3[6]; + Quaternion quaternion = Quaternion.AngleAxis(60f, Vector3.up); + ref Vector3 reference = ref array[0]; + reference = Vector3.forward * radius; + for (int i = 1; i < array.Length; i++) + { + ref Vector3 reference2 = ref array[i]; + reference2 = quaternion * reference; + reference = ref reference2; + } + return array; + } + + private static Vector3[] GeneratePointsFromPattern(GameObject patternObject) + { + Transform transform = patternObject.transform; + Vector3 position = transform.position; + List list = new List(); + for (int i = 0; i < transform.childCount; i++) + { + Transform child = transform.GetChild(i); + if (child.gameObject.activeInHierarchy) + { + list.Add(child.position - position); + } + } + return list.ToArray(); + } + + private static Vector3[] GenerateVelocitiesFromPoints(Vector3[] points, float apex) + { + Vector3[] array = new Vector3[points.Length]; + float num = Trajectory.CalculateInitialYSpeedForHeight(apex); + for (int i = 0; i < points.Length; i++) + { + Vector3 normalized = points[i].normalized; + float num2 = Trajectory.CalculateGroundSpeedToClearDistance(num, points[i].magnitude); + Vector3 vector = normalized * num2; + vector.y = num; + array[i] = vector; + } + return array; + } + + private static void ResolveVelocities() + { + if (!velocitiesResolved) + { + velocities = GenerateVelocitiesFromPoints(GeneratePoints(patternRadius), launchApex); + if (!Application.isEditor) + { + velocitiesResolved = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/WaitForDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/WaitForDeath.cs new file mode 100644 index 0000000..d34b3e2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/WaitForDeath.cs @@ -0,0 +1,17 @@ +using UnityEngine.Networking; + +namespace EntityStates.Engi.MineDeployer; + +public class WaitForDeath : BaseMineDeployerState +{ + public static float duration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && duration <= base.fixedAge) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/WaitForStick.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/WaitForStick.cs new file mode 100644 index 0000000..2825cf5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.MineDeployer/WaitForStick.cs @@ -0,0 +1,23 @@ +using RoR2.Projectile; + +namespace EntityStates.Engi.MineDeployer; + +public class WaitForStick : BaseMineDeployerState +{ + private ProjectileStickOnImpact projectileStickOnImpact; + + public override void OnEnter() + { + base.OnEnter(); + projectileStickOnImpact = GetComponent(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && projectileStickOnImpact.stuck) + { + outer.SetNextState(new FireMine()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/BaseSpiderMineState.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/BaseSpiderMineState.cs new file mode 100644 index 0000000..b41e494 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/BaseSpiderMineState.cs @@ -0,0 +1,65 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Engi.SpiderMine; + +public class BaseSpiderMineState : BaseState +{ + protected static int IdleToArmedStateHash = Animator.StringToHash("IdleToArmed"); + + protected static int IdleToArmedParamHash = Animator.StringToHash("IdleToArmed.playbackRate"); + + protected static int ArmedToChaseStateHash = Animator.StringToHash("ArmedToChase"); + + protected static int ArmedToChaseParamHash = Animator.StringToHash("ArmedToChase.playbackRate"); + + protected static int ChaseStateHash = Animator.StringToHash("Chase"); + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string childLocatorStringToEnable; + + protected ProjectileStickOnImpact projectileStickOnImpact { get; private set; } + + protected ProjectileTargetComponent projectileTargetComponent { get; private set; } + + protected ProjectileGhostController projectileGhostController { get; private set; } + + protected virtual bool shouldStick => false; + + public override void OnEnter() + { + base.OnEnter(); + projectileStickOnImpact = GetComponent(); + projectileTargetComponent = GetComponent(); + projectileGhostController = base.projectileController.ghost; + if ((bool)base.modelLocator && (bool)projectileGhostController) + { + base.modelLocator.modelBaseTransform = projectileGhostController.transform; + base.modelLocator.modelTransform = base.modelLocator.modelBaseTransform.Find("mdlEngiSpiderMine"); + base.modelLocator.preserveModel = true; + base.modelLocator.noCorpse = true; + } + if (projectileStickOnImpact.enabled != shouldStick) + { + projectileStickOnImpact.enabled = shouldStick; + } + Transform transform = FindModelChild(childLocatorStringToEnable); + if ((bool)transform) + { + transform.gameObject.SetActive(value: true); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + protected void EmitDustEffect() + { + if ((bool)projectileGhostController) + { + projectileGhostController.transform.Find("Ring").GetComponent().Play(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Burrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Burrow.cs new file mode 100644 index 0000000..cbf2225 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Burrow.cs @@ -0,0 +1,39 @@ +namespace EntityStates.Engi.SpiderMine; + +public class Burrow : BaseSpiderMineState +{ + public static float baseDuration; + + private float duration; + + protected override bool shouldStick => true; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + PlayAnimation("Base", BaseSpiderMineState.IdleToArmedStateHash, BaseSpiderMineState.IdleToArmedParamHash, duration); + EmitDustEffect(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + EntityState entityState = null; + if (!base.projectileStickOnImpact.stuck) + { + entityState = new WaitForStick(); + } + else if (duration <= base.fixedAge) + { + entityState = new WaitForTarget(); + } + if (entityState != null) + { + outer.SetNextState(entityState); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/ChaseTarget.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/ChaseTarget.cs new file mode 100644 index 0000000..65fab65 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/ChaseTarget.cs @@ -0,0 +1,111 @@ +using UnityEngine; + +namespace EntityStates.Engi.SpiderMine; + +public class ChaseTarget : BaseSpiderMineState +{ + private class OrientationHelper : MonoBehaviour + { + private Rigidbody rigidbody; + + private void Awake() + { + rigidbody = GetComponent(); + } + + private void OnCollisionStay(Collision collision) + { + int contactCount = collision.contactCount; + if (contactCount == 0) + { + return; + } + Vector3 forward = collision.GetContact(0).normal; + for (int i = 1; i < contactCount; i++) + { + Vector3 normal = collision.GetContact(i).normal; + if (forward.y < normal.y) + { + forward = normal; + } + } + rigidbody.MoveRotation(Quaternion.LookRotation(forward)); + } + } + + public static float speed; + + public static float triggerRadius; + + private bool passedDetonationRadius; + + private float bestDistance; + + private OrientationHelper orientationHelper; + + private Transform target => base.projectileTargetComponent.target; + + protected override bool shouldStick => false; + + public override void OnEnter() + { + base.OnEnter(); + passedDetonationRadius = false; + bestDistance = float.PositiveInfinity; + PlayAnimation("Base", BaseSpiderMineState.ChaseStateHash); + if (base.isAuthority) + { + orientationHelper = base.gameObject.AddComponent(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + if (!target) + { + base.rigidbody.AddForce(Vector3.up, ForceMode.VelocityChange); + outer.SetNextState(new WaitForStick()); + return; + } + Vector3 position = target.position; + Vector3 position2 = base.transform.position; + Vector3 vector = position - position2; + float magnitude = vector.magnitude; + float y = base.rigidbody.velocity.y; + Vector3 velocity = vector * (speed / magnitude); + velocity.y = y; + base.rigidbody.velocity = velocity; + if (!passedDetonationRadius && magnitude <= triggerRadius) + { + passedDetonationRadius = true; + } + if (magnitude < bestDistance) + { + bestDistance = magnitude; + } + else if (passedDetonationRadius) + { + outer.SetNextState(new PreDetonate()); + } + } + + public override void OnExit() + { + Transform transform = FindModelChild(childLocatorStringToEnable); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + if ((object)orientationHelper != null) + { + EntityState.Destroy(orientationHelper); + orientationHelper = null; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Detonate.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Detonate.cs new file mode 100644 index 0000000..ada9644 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Detonate.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.SpiderMine; + +public class Detonate : BaseSpiderMineState +{ + public static float blastRadius; + + public static GameObject blastEffectPrefab; + + [SerializeField] + private List childLocatorStringToDisable = new List { "Armed", "Chase", "PreDetonate" }; + + protected override bool shouldStick => false; + + public override void OnEnter() + { + base.OnEnter(); + if (!NetworkServer.active) + { + return; + } + ProjectileDamage component = GetComponent(); + Vector3 position = base.transform.position; + BlastAttack blastAttack = new BlastAttack(); + blastAttack.position = position; + blastAttack.attacker = base.projectileController.owner; + blastAttack.baseDamage = component.damage; + blastAttack.baseForce = component.force; + blastAttack.bonusForce = Vector3.zero; + blastAttack.crit = component.crit; + blastAttack.damageColorIndex = component.damageColorIndex; + blastAttack.damageType = component.damageType; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.inflictor = base.gameObject; + blastAttack.procChainMask = base.projectileController.procChainMask; + blastAttack.radius = blastRadius; + blastAttack.teamIndex = base.projectileController.teamFilter.teamIndex; + blastAttack.procCoefficient = base.projectileController.procCoefficient; + blastAttack.Fire(); + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = position, + scale = blastRadius + }, transmit: true); + float duration = 0.25f; + PlayAnimation("Base", BaseSpiderMineState.IdleToArmedStateHash, BaseSpiderMineState.IdleToArmedParamHash, duration); + foreach (string item in childLocatorStringToDisable) + { + Transform transform = FindModelChild(item); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + } + EntityState.Destroy(base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/PreDetonate.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/PreDetonate.cs new file mode 100644 index 0000000..d343d08 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/PreDetonate.cs @@ -0,0 +1,26 @@ +namespace EntityStates.Engi.SpiderMine; + +public class PreDetonate : BaseSpiderMineState +{ + public static float baseDuration; + + private float duration; + + protected override bool shouldStick => false; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + base.rigidbody.isKinematic = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && duration <= base.fixedAge) + { + outer.SetNextState(new Detonate()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Unburrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Unburrow.cs new file mode 100644 index 0000000..989b5da --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/Unburrow.cs @@ -0,0 +1,99 @@ +using System; +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.Engi.SpiderMine; + +public class Unburrow : BaseSpiderMineState +{ + public static float baseDuration; + + public static int betterTargetSearchLimit; + + private float duration; + + protected override bool shouldStick => true; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + Util.PlaySound("Play_beetle_worker_idle", base.gameObject); + PlayAnimation("Base", BaseSpiderMineState.ArmedToChaseStateHash, BaseSpiderMineState.ArmedToChaseParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + EntityState entityState = null; + if (!base.projectileStickOnImpact.stuck) + { + entityState = new WaitForStick(); + } + else if ((bool)base.projectileTargetComponent.target) + { + if (duration <= base.fixedAge) + { + FindBetterTarget(base.projectileTargetComponent.target); + entityState = new ChaseTarget(); + } + } + else + { + entityState = new Burrow(); + } + if (entityState != null) + { + outer.SetNextState(entityState); + } + } + + private BullseyeSearch CreateBullseyeSearch(Vector3 origin) + { + return new BullseyeSearch + { + searchOrigin = origin, + filterByDistinctEntity = true, + maxDistanceFilter = Detonate.blastRadius, + sortMode = BullseyeSearch.SortMode.Distance, + maxAngleFilter = 360f, + teamMaskFilter = TeamMask.GetEnemyTeams(base.projectileController.teamFilter.teamIndex) + }; + } + + private void FindBetterTarget(Transform initialTarget) + { + BullseyeSearch bullseyeSearch = CreateBullseyeSearch(initialTarget.position); + bullseyeSearch.RefreshCandidates(); + HurtBox[] array = bullseyeSearch.GetResults().ToArray(); + int num = array.Length; + int num2 = -1; + int i = 0; + for (int num3 = Math.Min(array.Length, betterTargetSearchLimit); i < num3; i++) + { + HurtBox hurtBox = array[i]; + int num4 = CountTargets(hurtBox.transform.position); + if (num < num4) + { + num = num4; + num2 = i; + } + } + if (num2 != -1) + { + base.projectileTargetComponent.target = array[num2].transform; + } + } + + private int CountTargets(Vector3 origin) + { + BullseyeSearch bullseyeSearch = CreateBullseyeSearch(origin); + bullseyeSearch.RefreshCandidates(); + return bullseyeSearch.GetResults().Count(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/WaitForStick.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/WaitForStick.cs new file mode 100644 index 0000000..5916941 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/WaitForStick.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +namespace EntityStates.Engi.SpiderMine; + +public class WaitForStick : BaseSpiderMineState +{ + private static int IdleStateHash = Animator.StringToHash("Idle"); + + protected override bool shouldStick => true; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", IdleStateHash); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.projectileStickOnImpact.stuck) + { + outer.SetNextState(new Burrow()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/WaitForTarget.cs b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/WaitForTarget.cs new file mode 100644 index 0000000..5ca4f03 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Engi.SpiderMine/WaitForTarget.cs @@ -0,0 +1,55 @@ +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Engi.SpiderMine; + +public class WaitForTarget : BaseSpiderMineState +{ + private static int ArmedStateHash = Animator.StringToHash("Armed"); + + protected ProjectileSphereTargetFinder targetFinder { get; private set; } + + protected override bool shouldStick => true; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + targetFinder = GetComponent(); + targetFinder.enabled = true; + } + PlayAnimation("Base", ArmedStateHash); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + EntityState entityState = null; + if (!base.projectileStickOnImpact.stuck) + { + entityState = new WaitForStick(); + } + else if ((bool)base.projectileTargetComponent.target) + { + entityState = new Unburrow(); + } + if (entityState != null) + { + outer.SetNextState(entityState); + } + } + } + + public override void OnExit() + { + if ((bool)targetFinder) + { + targetFinder.enabled = false; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.EngiTurret.EngiTurretWeapon/FireBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.EngiTurret.EngiTurretWeapon/FireBeam.cs new file mode 100644 index 0000000..f11bfed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.EngiTurret.EngiTurretWeapon/FireBeam.cs @@ -0,0 +1,263 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.EngiTurret.EngiTurretWeapon; + +public class FireBeam : BaseState +{ + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject laserPrefab; + + [SerializeField] + public string muzzleString; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public float minSpread; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public int bulletCount; + + [SerializeField] + public float fireFrequency; + + [SerializeField] + public float maxDistance; + + private float fireTimer; + + private Ray laserRay; + + private Transform modelTransform; + + private GameObject laserEffectInstance; + + private Transform laserEffectInstanceEndTransform; + + private Vector3 laserEndPoint; + + private float prevLaserDistance; + + private bool forceCast; + + private BulletAttack bulletAttack; + + private EffectManagerHelper _emh_laserEffect; + + public override void Reset() + { + base.Reset(); + fireTimer = 0f; + laserEndPoint = Vector3.zero; + modelTransform = null; + laserEffectInstance = null; + laserEffectInstanceEndTransform = null; + forceCast = true; + if (bulletAttack != null) + { + bulletAttack.Reset(); + } + _emh_laserEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(attackSoundString, base.gameObject); + fireTimer = 0f; + forceCast = true; + modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild(muzzleString); + if ((bool)transform && (bool)laserPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(laserPrefab)) + { + laserEffectInstance = Object.Instantiate(laserPrefab, transform.position, transform.rotation); + } + else + { + _emh_laserEffect = EffectManager.GetAndActivatePooledEffect(laserPrefab, transform.position, transform.rotation); + laserEffectInstance = _emh_laserEffect.gameObject; + } + if ((bool)laserEffectInstance) + { + ChildLocator component2 = laserEffectInstance.GetComponent(); + laserEffectInstanceEndTransform = component2.FindChild("LaserEnd"); + } + laserEffectInstance.transform.parent = transform; + } + } + + public override void OnExit() + { + if ((bool)laserEffectInstance) + { + if (_emh_laserEffect != null && _emh_laserEffect.OwningPool != null) + { + _emh_laserEffect.OwningPool.ReturnObject(_emh_laserEffect); + } + else + { + EntityState.Destroy(laserEffectInstance); + } + laserEffectInstance = null; + _emh_laserEffect = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!(Time.deltaTime > 0f)) + { + return; + } + laserRay = GetLaserRay(); + fireTimer += Time.deltaTime; + float num = fireFrequency * base.characterBody.attackSpeed; + float num2 = 1f / num; + if (fireTimer > num2) + { + if (base.isAuthority) + { + laserEndPoint = FireBullet(laserRay, muzzleString); + prevLaserDistance = (laserEndPoint - laserRay.origin).magnitude; + } + else + { + forceCast = true; + } + fireTimer = 0f; + } + else if (!forceCast && prevLaserDistance > float.Epsilon) + { + laserEndPoint = laserRay.origin + laserRay.direction * prevLaserDistance; + } + if (forceCast) + { + forceCast = false; + if ((bool)laserEffectInstance && (bool)laserEffectInstanceEndTransform) + { + float distance = maxDistance; + _ = laserEffectInstance.transform.parent.position; + laserEndPoint = laserRay.GetPoint(distance); + if (Util.CharacterRaycast(base.gameObject, laserRay, out var hitInfo, distance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + laserEndPoint = hitInfo.point; + prevLaserDistance = (laserEndPoint - laserRay.origin).magnitude; + } + } + } + if ((bool)laserEffectInstance && (bool)laserEffectInstanceEndTransform) + { + laserEffectInstanceEndTransform.position = laserEndPoint; + } + if (base.isAuthority && !ShouldFireLaser()) + { + outer.SetNextStateToMain(); + } + } + + protected Vector3 GetBeamEndPoint() + { + Vector3 point = laserRay.GetPoint(maxDistance); + if (Util.CharacterRaycast(base.gameObject, laserRay, out var hitInfo, maxDistance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + point = hitInfo.point; + } + return point; + } + + protected virtual EntityState GetNextState() + { + return EntityStateCatalog.InstantiateState(ref outer.mainStateType); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public virtual void ModifyBullet(BulletAttack bulletAttack) + { + bulletAttack.damageType |= (DamageTypeCombo)DamageType.SlowOnHit; + } + + public virtual bool ShouldFireLaser() + { + if ((bool)base.inputBank) + { + return base.inputBank.skill1.down; + } + return false; + } + + public virtual Ray GetLaserRay() + { + return GetAimRay(); + } + + private Vector3 FireBullet(Ray laserRay, string targetMuzzle) + { + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + if (bulletAttack == null) + { + bulletAttack = new BulletAttack(); + } + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = laserRay.origin; + bulletAttack.aimVector = laserRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat / fireFrequency; + bulletAttack.procCoefficient = procCoefficient / fireFrequency; + bulletAttack.force = force; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0f; + bulletAttack.maxDistance = maxDistance; + ModifyBullet(bulletAttack); + return bulletAttack.Fire_ReturnHit(); + } + return Vector3.zero; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.EngiTurret.EngiTurretWeapon/FireGauss.cs b/ilspy_dump/ror2_csproj/EntityStates.EngiTurret.EngiTurretWeapon/FireGauss.cs new file mode 100644 index 0000000..aaf46c1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.EngiTurret.EngiTurretWeapon/FireGauss.cs @@ -0,0 +1,89 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.EngiTurret.EngiTurretWeapon; + +public class FireGauss : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static string attackSoundString; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public int bulletCountCurrent = 1; + + private float duration; + + private static int FireGaussStateHash = Animator.StringToHash("FireGauss"); + + private static int FireGaussParamHash = Animator.StringToHash("FireGauss.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(attackSoundString, base.gameObject); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + PlayAnimation("Gesture", FireGaussStateHash, FireGaussParamHash, duration); + string muzzleName = "Muzzle"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0.15f; + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.EngiTurret/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.EngiTurret/DeathState.cs new file mode 100644 index 0000000..fd9e111 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.EngiTurret/DeathState.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.EngiTurret; + +public class DeathState : GenericCharacterDeath +{ + [SerializeField] + public GameObject initialExplosion; + + [SerializeField] + public GameObject deathExplosion; + + private float deathDuration; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.PlayInFixedTime("Death", layerIndex); + modelAnimator.Update(0f); + deathDuration = modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).length; + if ((bool)initialExplosion) + { + Object.Instantiate(initialExplosion, base.transform.position, base.transform.rotation, base.transform); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > deathDuration && NetworkServer.active && (bool)deathExplosion) + { + EffectManager.SpawnEffect(deathExplosion, new EffectData + { + origin = base.transform.position, + scale = 2f + }, transmit: true); + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/AurelioniteCore.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/AurelioniteCore.cs new file mode 100644 index 0000000..eaaf393 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/AurelioniteCore.cs @@ -0,0 +1,8 @@ +namespace EntityStates.FalseSon; + +public class AurelioniteCore : BaseState +{ + public override void OnEnter() + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ChargedClubSwing.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ChargedClubSwing.cs new file mode 100644 index 0000000..6254bf5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ChargedClubSwing.cs @@ -0,0 +1,175 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class ChargedClubSwing : BaseState +{ + [SerializeField] + public float baseDuration; + + public float charge; + + public bool chargeMetMinimumHold; + + public static float playerWalkSpeedCoefficient; + + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static string enterSoundString; + + public static Vector3 blastBonusForce; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static GameObject swingEffectPrefab; + + public static float percentOfDurationToFireSwingEffect; + + public static float unchargedBlastRadius; + + public static float unchargedBlastProcCoefficient; + + public static float unchargedBlastDamageCoefficient; + + public static float unchargedBlastForce; + + public static Vector3 unchargedBlastBonusForce; + + public static GameObject unchargedSwingVFX; + + public static float percentOfAnimationToHoldPlayer; + + private GameObject swingEffectInstance; + + private bool wasSprinting; + + private bool authorityDetonated; + + private bool detonateNextFrame; + + private bool firedSwingVFX; + + public override void OnEnter() + { + base.OnEnter(); + baseDuration /= attackSpeedStat; + PlayAnimation("FullBody, Override", "OverheadSwing", "ChargeSwing.playbackRate", baseDuration); + wasSprinting = base.characterBody.isSprinting; + base.characterMotor.walkSpeedPenaltyCoefficient = playerWalkSpeedCoefficient; + if (chargeMetMinimumHold && base.isAuthority) + { + EffectData effectData = new EffectData(); + ChildLocator modelChildLocator = GetModelChildLocator(); + effectData.SetChildLocatorTransformReference(base.gameObject, modelChildLocator.FindChildIndex("OverHeadSwingPoint")); + EffectManager.SpawnEffect(swingEffectPrefab, effectData, transmit: false); + } + base.characterBody.GetComponent()?.SetClubSwingAltSecondaryTimestamp(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (!chargeMetMinimumHold && !firedSwingVFX && base.fixedAge >= minimumDuration * percentOfDurationToFireSwingEffect) + { + SpawnSwingEffect(); + firedSwingVFX = true; + } + if (!authorityDetonated && base.fixedAge >= minimumDuration) + { + DetonateAuthority(); + authorityDetonated = true; + } + if (base.fixedAge >= baseDuration * percentOfAnimationToHoldPlayer) + { + outer.SetNextStateToMain(); + } + } + } + + private void SpawnSwingEffect() + { + EffectData effectData = new EffectData(); + ChildLocator modelChildLocator = GetModelChildLocator(); + effectData.SetChildLocatorTransformReference(base.gameObject, modelChildLocator.FindChildIndex("SwingVertical")); + EffectManager.SpawnEffect(unchargedSwingVFX, effectData, transmit: true); + } + + public override void OnExit() + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + base.characterBody.isSprinting = wasSprinting; + base.characterBody.SetSpreadBloom(0f, canOnlyIncreaseBloom: false); + base.OnExit(); + } + + protected BlastAttack.Result DetonateAuthority() + { + BlastAttack blast = new BlastAttack(); + if (chargeMetMinimumHold) + { + InitializeBlastAttackAsCharged(ref blast); + } + else + { + InitializeBlastAttackNormal(ref blast); + } + return blast.Fire(); + } + + private void InitializeBlastAttackAsCharged(ref BlastAttack blast) + { + Vector3 position = FindModelChild("ClubExplosionPoint").transform.position; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = position, + scale = blastRadius * (charge + 1.25f) + }, transmit: true); + blast.attacker = base.gameObject; + blast.baseDamage = damageStat * (blastDamageCoefficient * charge) + (base.characterBody.maxHealth - (base.characterBody.baseMaxHealth + base.characterBody.levelMaxHealth * (float)((int)base.characterBody.level - 1))) * 0.01f; + blast.baseForce = blastForce; + blast.bonusForce = blastBonusForce; + blast.crit = RollCrit(); + blast.falloffModel = BlastAttack.FalloffModel.None; + blast.procCoefficient = blastProcCoefficient; + blast.radius = blastRadius * (charge + 1.55f); + blast.position = position; + blast.attackerFiltering = AttackerFiltering.NeverHitSelf; + blast.impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab); + blast.teamIndex = base.teamComponent.teamIndex; + } + + private void InitializeBlastAttackNormal(ref BlastAttack blast) + { + Vector3 position = FindModelChild("ClubExplosionPoint").transform.position; + blast.attacker = base.gameObject; + blast.baseDamage = damageStat * (unchargedBlastDamageCoefficient * charge); + blast.baseForce = unchargedBlastForce; + blast.bonusForce = unchargedBlastBonusForce; + blast.crit = RollCrit(); + blast.falloffModel = BlastAttack.FalloffModel.None; + blast.procCoefficient = unchargedBlastProcCoefficient; + blast.radius = unchargedBlastRadius; + blast.position = position; + blast.attackerFiltering = AttackerFiltering.NeverHitSelf; + blast.impactEffect = EffectIndex.Invalid; + blast.teamIndex = base.teamComponent.teamIndex; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubForsaken.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubForsaken.cs new file mode 100644 index 0000000..c2d7a3e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubForsaken.cs @@ -0,0 +1,240 @@ +using System; +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSon; + +public class ClubForsaken : BaseSkillState, SteppedSkillDef.IStepSetter +{ + private class ArcVisualizer : IDisposable + { + private readonly Vector3[] points; + + private readonly float duration; + + private readonly GameObject arcVisualizerInstance; + + private readonly LineRenderer lineRenderer; + + public ArcVisualizer(GameObject arcVisualizerPrefab, float duration, int vertexCount) + { + arcVisualizerInstance = UnityEngine.Object.Instantiate(arcVisualizerPrefab); + lineRenderer = arcVisualizerInstance.GetComponent(); + lineRenderer.positionCount = vertexCount; + points = new Vector3[vertexCount]; + this.duration = duration; + } + + public void Dispose() + { + EntityState.Destroy(arcVisualizerInstance); + } + + public void SetParameters(Vector3 origin, Vector3 initialVelocity, float characterMaxSpeed, float characterAcceleration) + { + arcVisualizerInstance.transform.position = origin; + if (!lineRenderer.useWorldSpace) + { + Vector3 eulerAngles = Quaternion.LookRotation(initialVelocity).eulerAngles; + eulerAngles.x = 0f; + eulerAngles.z = 0f; + Quaternion rotation = Quaternion.Euler(eulerAngles); + arcVisualizerInstance.transform.rotation = rotation; + origin = Vector3.zero; + initialVelocity = Quaternion.Inverse(rotation) * initialVelocity; + } + else + { + arcVisualizerInstance.transform.rotation = Quaternion.LookRotation(Vector3.Cross(initialVelocity, Vector3.up)); + } + float y = Physics.gravity.y; + float num = duration / (float)points.Length; + Vector3 vector = origin; + Vector3 vector2 = initialVelocity; + float num2 = num; + float num3 = y * num2; + float maxDistanceDelta = characterAcceleration * num2; + for (int i = 0; i < points.Length; i++) + { + points[i] = vector; + Vector2 current = Util.Vector3XZToVector2XY(vector2); + current = Vector2.MoveTowards(current, Vector3.zero, maxDistanceDelta); + vector2.x = current.x; + vector2.z = current.y; + vector2.y += num3; + vector += vector2 * num2; + } + lineRenderer.SetPositions(points); + } + } + + public int clubState; + + public static GameObject arcVisualizerPrefab; + + public static float arcVisualizerSimulationLength; + + public static int arcVisualizerVertexCount; + + [SerializeField] + public float baseChargeDuration = 1f; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private Transform chargeVfxInstanceTransform; + + private int gauntlet; + + private uint soundID; + + private bool chargeAnimPlayed; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + clubState = i; + } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration / attackSpeedStat; + Util.PlaySound(enterSFXString, base.gameObject); + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnExit() + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + crosshairOverrideRequest?.Dispose(); + chargeVfxInstanceTransform = null; + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + AkSoundEngine.SetRTPCValueByPlayingID("charFalseSon_skill1_chargeAmount", charge * 100f, soundID); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeForChargedAttack && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + if ((bool)crosshairOverridePrefab && crosshairOverrideRequest == null) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform) + { + chargeVfxInstanceTransform = UnityEngine.Object.Instantiate(chargeVfxPrefab, transform).transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeForChargedAttack) * chargeDuration; + } + } + if (!chargeAnimPlayed) + { + PlayCrossfade("Gesture, Additive", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + PlayCrossfade("Gesture, Override", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + chargeAnimPlayed = true; + } + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + public override void Update() + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + + private void AuthorityFixedUpdate() + { + if (!ShouldKeepChargingAuthority()) + { + outer.SetNextState(GetNextStateAuthority()); + } + } + + protected virtual bool ShouldKeepChargingAuthority() + { + return IsKeyDownAuthority(); + } + + protected virtual EntityState GetNextStateAuthority() + { + if (charge > minChargeForChargedAttack) + { + if (!base.isGrounded) + { + return new PreClubGroundSlam + { + charge = charge + }; + } + return new ChargedClubSwing + { + charge = charge + }; + } + return new ClubSwing2 + { + club = clubState + }; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)clubState); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + clubState = reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubForsaken2.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubForsaken2.cs new file mode 100644 index 0000000..9cd282a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubForsaken2.cs @@ -0,0 +1,212 @@ +using System; +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class ClubForsaken2 : BaseSkillState +{ + private class ArcVisualizer : IDisposable + { + private readonly Vector3[] points; + + private readonly float duration; + + private readonly GameObject arcVisualizerInstance; + + private readonly LineRenderer lineRenderer; + + public ArcVisualizer(GameObject arcVisualizerPrefab, float duration, int vertexCount) + { + arcVisualizerInstance = UnityEngine.Object.Instantiate(arcVisualizerPrefab); + lineRenderer = arcVisualizerInstance.GetComponent(); + lineRenderer.positionCount = vertexCount; + points = new Vector3[vertexCount]; + this.duration = duration; + } + + public void Dispose() + { + EntityState.Destroy(arcVisualizerInstance); + } + + public void SetParameters(Vector3 origin, Vector3 initialVelocity, float characterMaxSpeed, float characterAcceleration) + { + arcVisualizerInstance.transform.position = origin; + if (!lineRenderer.useWorldSpace) + { + Vector3 eulerAngles = Quaternion.LookRotation(initialVelocity).eulerAngles; + eulerAngles.x = 0f; + eulerAngles.z = 0f; + Quaternion rotation = Quaternion.Euler(eulerAngles); + arcVisualizerInstance.transform.rotation = rotation; + origin = Vector3.zero; + initialVelocity = Quaternion.Inverse(rotation) * initialVelocity; + } + else + { + arcVisualizerInstance.transform.rotation = Quaternion.LookRotation(Vector3.Cross(initialVelocity, Vector3.up)); + } + float y = Physics.gravity.y; + float num = duration / (float)points.Length; + Vector3 vector = origin; + Vector3 vector2 = initialVelocity; + float num2 = num; + float num3 = y * num2; + float maxDistanceDelta = characterAcceleration * num2; + for (int i = 0; i < points.Length; i++) + { + points[i] = vector; + Vector2 current = Util.Vector3XZToVector2XY(vector2); + current = Vector2.MoveTowards(current, Vector3.zero, maxDistanceDelta); + vector2.x = current.x; + vector2.z = current.y; + vector2.y += num3; + vector += vector2 * num2; + } + lineRenderer.SetPositions(points); + } + } + + public static GameObject arcVisualizerPrefab; + + public static float arcVisualizerSimulationLength; + + public static int arcVisualizerVertexCount; + + [SerializeField] + public float baseChargeDuration = 1f; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private Transform chargeVfxInstanceTransform; + + private int gauntlet; + + private uint soundID; + + private bool chargeAnimPlayed; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration / attackSpeedStat; + Util.PlaySound(enterSFXString, base.gameObject); + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnExit() + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + crosshairOverrideRequest?.Dispose(); + chargeVfxInstanceTransform = null; + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + AkSoundEngine.SetRTPCValueByPlayingID("charFalseSon_skill1_chargeAmount", charge * 100f, soundID); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeForChargedAttack && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + if ((bool)crosshairOverridePrefab && crosshairOverrideRequest == null) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform) + { + chargeVfxInstanceTransform = UnityEngine.Object.Instantiate(chargeVfxPrefab, transform).transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeForChargedAttack) * chargeDuration; + } + } + if (!chargeAnimPlayed) + { + PlayCrossfade("Gesture, Additive", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + PlayCrossfade("Gesture, Override", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + chargeAnimPlayed = true; + } + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + public override void Update() + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + + private void AuthorityFixedUpdate() + { + if (!ShouldKeepChargingAuthority()) + { + outer.SetNextState(GetNextStateAuthority()); + } + } + + protected virtual bool ShouldKeepChargingAuthority() + { + return IsKeyDownAuthority(); + } + + protected virtual EntityState GetNextStateAuthority() + { + if (!base.isGrounded) + { + return new PreClubGroundSlam + { + charge = charge + }; + } + return new ChargedClubSwing + { + charge = charge + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubGroundSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubGroundSlam.cs new file mode 100644 index 0000000..b392fa2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubGroundSlam.cs @@ -0,0 +1,166 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class ClubGroundSlam : BaseState +{ + public float charge; + + public static float airControl; + + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static string enterSoundString; + + public static float initialVerticalVelocity; + + public static float exitVerticalVelocity; + + public static float verticalAcceleration; + + public static float exitSlowdownCoefficient; + + public static Vector3 blastBonusForce; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static float normalizedVFXPositionBetweenFootAndClub; + + public static float normalizedBlastPositionBetweenFootAndClub; + + public static float smallHopVelocity; + + public static float heightInfluencePercent; + + private float previousAirControl; + + private float timeInAir; + + private float airClubTimer; + + private bool hitTheGround; + + private float delayBeforeExit; + + private bool detonateNextFrame; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "GroundSlam", 0.2f); + if (base.isAuthority) + { + base.characterMotor.onHitGroundAuthority += OnHitGroundAuthority; + base.characterMotor.velocity.y = initialVerticalVelocity; + } + Util.PlaySound(enterSoundString, base.gameObject); + previousAirControl = base.characterMotor.airControl; + base.characterMotor.airControl = airControl; + base.characterBody.bodyFlags |= CharacterBody.BodyFlags.IgnoreFallDamage; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + airClubTimer += deltaTime; + timeInAir = 0f; + if (airClubTimer > 0.5f) + { + timeInAir = airClubTimer; + } + if (base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.moveDirection = base.inputBank.moveVector; + base.characterDirection.moveVector = base.characterMotor.moveDirection; + base.characterMotor.velocity.y += verticalAcceleration * deltaTime; + if (!hitTheGround && base.fixedAge >= minimumDuration && (detonateNextFrame || (base.characterMotor.Motor.GroundingStatus.IsStableOnGround && !base.characterMotor.Motor.LastGroundingStatus.IsStableOnGround))) + { + PlayAnimation("Body", "GroundSlamExit"); + DetonateAuthority(); + hitTheGround = true; + delayBeforeExit = base.fixedAge; + } + else if (hitTheGround && base.fixedAge >= delayBeforeExit + 0.1f) + { + outer.SetNextStateToMain(); + } + else + { + base.characterBody.SetSpreadBloom(charge); + } + } + } + + public override void OnExit() + { + if (!base.isAuthority) + { + PlayAnimation("Body", "GroundSlamExit"); + } + base.characterBody.SetSpreadBloom(0f, canOnlyIncreaseBloom: false); + if (base.isAuthority) + { + base.characterMotor.onHitGroundAuthority -= OnHitGroundAuthority; + base.characterMotor.velocity *= exitSlowdownCoefficient; + base.characterMotor.velocity.y = exitVerticalVelocity; + if (!hitTheGround) + { + PlayAnimation("Body", "Idle"); + } + } + base.characterMotor.airControl = previousAirControl; + base.characterBody.bodyFlags &= ~CharacterBody.BodyFlags.IgnoreFallDamage; + SmallHop(base.characterMotor, smallHopVelocity + airClubTimer * heightInfluencePercent); + base.OnExit(); + } + + private void OnHitGroundAuthority(ref CharacterMotor.HitGroundInfo hitGroundInfo) + { + detonateNextFrame = true; + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 position = FindModelChild("ClubExplosionPoint").transform.position; + Vector3 footPosition = base.characterBody.footPosition; + Vector3 origin = footPosition + (position - footPosition) * normalizedVFXPositionBetweenFootAndClub; + Vector3 position2 = footPosition + (position - footPosition) * normalizedBlastPositionBetweenFootAndClub; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = origin, + scale = blastRadius * (charge + 1.25f + timeInAir * 2f) + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * (blastDamageCoefficient * charge) + (base.characterBody.maxHealth - (base.characterBody.baseMaxHealth + base.characterBody.levelMaxHealth * (float)((int)base.characterBody.level - 1))) * 0.01f, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius * (charge + 1.25f + timeInAir * 2f), + position = position2, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing.cs new file mode 100644 index 0000000..cbae6d7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing.cs @@ -0,0 +1,186 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSon; + +public class ClubSwing : BasicMeleeAttack, SteppedSkillDef.IStepSetter, ISkillOverrideHandoff +{ + public int club; + + public static GameObject secondarySwingEffectPrefab; + + [SerializeField] + public SkillDef secondaryOverrideSkill; + + [SerializeField] + public SkillDef specialOverrideSkill; + + [SerializeField] + public float secondaryAltCooldownDuration = 0.7f; + + private SkillStateOverrideData skillOverrideData; + + private float startTimeStamp; + + private bool resetClubSwing; + + private bool clearOverrides = true; + + private FalseSonController falseSonController; + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + club = i; + } + + public override void OnEnter() + { + base.OnEnter(); + falseSonController = base.characterBody.GetComponent(); + if (CheckReadyForSecondaryAlt()) + { + GenerateSkillOverrideData(); + } + else + { + EnsureSkillOverrideState(readyToFire: false); + } + clearOverrides = true; + startTimeStamp = Time.time; + } + + void ISkillOverrideHandoff.TransferSkillOverride(SkillStateOverrideData skillOverrideData) + { + this.skillOverrideData = skillOverrideData; + } + + private bool CheckReadyForSecondaryAlt() + { + if (base.inputBank.skill1.down) + { + return Time.time - falseSonController.GetClubSwingAltSecondaryTimestamp() > secondaryAltCooldownDuration; + } + return false; + } + + private void EnsureSkillOverrideState(bool readyToFire) + { + if (readyToFire ^ (skillOverrideData != null)) + { + if (readyToFire) + { + GenerateSkillOverrideData(); + } + else + { + ClearSkillOverrideData(); + } + } + } + + private void GenerateSkillOverrideData() + { + if (skillOverrideData == null) + { + skillOverrideData = new SkillStateOverrideData(base.characterBody); + skillOverrideData.secondarySkillOverride = secondaryOverrideSkill; + skillOverrideData.overrideFullReloadOnAssign = true; + skillOverrideData.simulateRestockForOverridenSkills = false; + skillOverrideData.OverrideSkills(base.skillLocator); + } + } + + private void ClearSkillOverrideData() + { + if (skillOverrideData != null) + { + skillOverrideData.ClearOverrides(); + } + skillOverrideData = null; + } + + public override void FixedUpdate() + { + if (skillOverrideData != null) + { + skillOverrideData.StepRestock(); + } + bool flag = CheckReadyForSecondaryAlt(); + EnsureSkillOverrideState(flag); + if (flag && base.inputBank.skill2.justPressed) + { + ResetClubSwing(); + outer.SetNextState(GetNextStateAuthority()); + } + base.FixedUpdate(); + } + + private void ResetClubSwing() + { + SteppedSkillDef.InstanceData instanceData = (SteppedSkillDef.InstanceData)(base.skillLocator.GetSkill(SkillSlot.Primary)?.skillInstanceData); + if (instanceData != null) + { + instanceData.step = 0; + club = 0; + resetClubSwing = true; + } + } + + protected override void PlayAnimation() + { + string animationStateName = ((club == 0) ? "SwingClubRight" : "SwingClubLeft"); + float num = Mathf.Max(duration, 0.2f); + PlayCrossfade("Gesture, Additive", animationStateName, "SwingClub.playbackRate", num, 0.1f); + PlayCrossfade("Gesture, Override", animationStateName, "SwingClub.playbackRate", num, 0.1f); + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectPrefab = ((club == 0) ? swingEffectPrefab : secondarySwingEffectPrefab); + swingEffectMuzzleString = ((club == 0) ? "SwingRight" : "SwingLeft"); + base.BeginMeleeAttackEffect(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)club); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + club = reader.ReadByte(); + } + + public override void OnExit() + { + base.OnExit(); + if (clearOverrides && skillOverrideData != null) + { + skillOverrideData.ClearOverrides(); + } + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is ISkillOverrideHandoff skillOverrideHandoff && skillOverrideData != null) + { + skillOverrideHandoff.TransferSkillOverride(skillOverrideData); + clearOverrides = false; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + protected virtual EntityState GetNextStateAuthority() + { + return new ClubSwing3(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing2.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing2.cs new file mode 100644 index 0000000..a09b1ad --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing2.cs @@ -0,0 +1,148 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSon; + +public class ClubSwing2 : BasicMeleeAttack, SteppedSkillDef.IStepSetter +{ + public int club; + + public static float recoilAmplitude; + + public static float baseDurationBeforeInterruptable; + + [SerializeField] + public float bloom; + + public static float comboFinisherBaseDuration; + + public static GameObject comboFinisherSwingEffectPrefab; + + public static float comboFinisherhitPauseDuration; + + public static float comboFinisherDamageCoefficient; + + public static float comboFinisherBloom; + + public static float comboFinisherBaseDurationBeforeInterruptable; + + public static string slash1Sound; + + public static string slash3Sound; + + private string animationStateName; + + private string meleeStreakStateName; + + private float durationBeforeInterruptable; + + private bool isComboFinisher => club == 1; + + protected override bool allowExitFire + { + get + { + if ((bool)base.characterBody) + { + return !base.characterBody.isSprinting; + } + return false; + } + } + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + club = i; + } + + public override void OnEnter() + { + base.OnEnter(); + if (isComboFinisher) + { + swingEffectPrefab = comboFinisherSwingEffectPrefab; + hitPauseDuration = comboFinisherhitPauseDuration; + damageCoefficient = comboFinisherDamageCoefficient; + bloom = comboFinisherBloom; + hitBoxGroupName = "SwordLarge"; + baseDuration = comboFinisherBaseDuration; + } + base.OnEnter(); + base.characterDirection.forward = GetAimRay().direction; + durationBeforeInterruptable = (isComboFinisher ? (comboFinisherBaseDurationBeforeInterruptable / attackSpeedStat) : (baseDurationBeforeInterruptable / attackSpeedStat)); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + _ = isComboFinisher; + } + + protected override void PlayAnimation() + { + animationStateName = ""; + string soundString = null; + switch (club) + { + case 0: + animationStateName = "SwingClubRight"; + meleeStreakStateName = "SwingRight"; + soundString = slash1Sound; + break; + case 1: + animationStateName = "SwingClubLeft"; + meleeStreakStateName = "SwingLeft"; + soundString = slash1Sound; + break; + } + bool @bool = animator.GetBool("isMoving"); + bool bool2 = animator.GetBool("isGrounded"); + if (!@bool && bool2) + { + PlayCrossfade("FullBody, Override", animationStateName, "SwingClub.playbackRate", duration, 0.05f); + } + else + { + PlayCrossfade("Gesture, Additive", animationStateName, "SwingClub.playbackRate", duration, 0.05f); + PlayCrossfade("Gesture, Override", animationStateName, "SwingClub.playbackRate", duration, 0.05f); + } + Util.PlaySound(soundString, base.gameObject); + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + base.characterBody.AddSpreadBloom(bloom); + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectMuzzleString = meleeStreakStateName; + AddRecoil(-0.1f * recoilAmplitude, 0.1f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + base.BeginMeleeAttackEffect(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)club); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + club = reader.ReadByte(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing3.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing3.cs new file mode 100644 index 0000000..86b3a60 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/ClubSwing3.cs @@ -0,0 +1,309 @@ +using System; +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class ClubSwing3 : BaseSkillState, ISkillOverrideHandoff +{ + private class ArcVisualizer : IDisposable + { + private readonly Vector3[] points; + + private readonly float duration; + + private readonly GameObject arcVisualizerInstance; + + private readonly LineRenderer lineRenderer; + + public ArcVisualizer(GameObject arcVisualizerPrefab, float duration, int vertexCount) + { + arcVisualizerInstance = UnityEngine.Object.Instantiate(arcVisualizerPrefab); + lineRenderer = arcVisualizerInstance.GetComponent(); + lineRenderer.positionCount = vertexCount; + points = new Vector3[vertexCount]; + this.duration = duration; + } + + public void Dispose() + { + EntityState.Destroy(arcVisualizerInstance); + } + + public void SetParameters(Vector3 origin, Vector3 initialVelocity, float characterMaxSpeed, float characterAcceleration) + { + arcVisualizerInstance.transform.position = origin; + if (!lineRenderer.useWorldSpace) + { + Vector3 eulerAngles = Quaternion.LookRotation(initialVelocity).eulerAngles; + eulerAngles.x = 0f; + eulerAngles.z = 0f; + Quaternion rotation = Quaternion.Euler(eulerAngles); + arcVisualizerInstance.transform.rotation = rotation; + origin = Vector3.zero; + initialVelocity = Quaternion.Inverse(rotation) * initialVelocity; + } + else + { + arcVisualizerInstance.transform.rotation = Quaternion.LookRotation(Vector3.Cross(initialVelocity, Vector3.up)); + } + float y = Physics.gravity.y; + float num = duration / (float)points.Length; + Vector3 vector = origin; + Vector3 vector2 = initialVelocity; + float num2 = num; + float num3 = y * num2; + float maxDistanceDelta = characterAcceleration * num2; + for (int i = 0; i < points.Length; i++) + { + points[i] = vector; + Vector2 current = Util.Vector3XZToVector2XY(vector2); + current = Vector2.MoveTowards(current, Vector3.zero, maxDistanceDelta); + vector2.x = current.x; + vector2.z = current.y; + vector2.y += num3; + vector += vector2 * num2; + } + lineRenderer.SetPositions(points); + } + } + + public static GameObject arcVisualizerPrefab; + + public static float arcVisualizerSimulationLength; + + public static int arcVisualizerVertexCount; + + [SerializeField] + public float baseChargeDuration = 1f; + + [SerializeField] + public float minChargeToDisplayAttackCharging; + + [SerializeField] + public float minChargeToChargeAttack; + + [SerializeField] + public float cooldownOnCancelDuration = 1f; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private Transform chargeVfxInstanceTransform; + + private int gauntlet; + + private uint soundID; + + private bool chargeAnimPlayed; + + private SkillStateOverrideData skillOverrideData; + + private bool clearOverrides = true; + + private bool nonAuthority_AllowEarlyCancelAnimationToFinish; + + private float cooldownTimestamp = -1f; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration / attackSpeedStat; + Util.PlaySound(enterSFXString, base.gameObject); + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + clearOverrides = true; + ResetPrimarySwingCount(); + } + + private void ResetPrimarySwingCount() + { + SteppedSkillDef.InstanceData instanceData = (SteppedSkillDef.InstanceData)(base.skillLocator.GetSkill(SkillSlot.Primary)?.skillInstanceData); + if (instanceData != null) + { + instanceData.step = 0; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void FixedUpdate() + { + if (skillOverrideData != null) + { + skillOverrideData.StepRestock(); + } + if (cooldownTimestamp != -1f) + { + if (!(Time.time - cooldownTimestamp < cooldownOnCancelDuration)) + { + outer.SetNextStateToMain(); + } + return; + } + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + AkSoundEngine.SetRTPCValueByPlayingID("charFalseSon_skill1_chargeAmount", charge * 100f, soundID); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeToDisplayAttackCharging && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + if ((bool)crosshairOverridePrefab && crosshairOverrideRequest == null) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform && charge > minChargeToChargeAttack) + { + chargeVfxInstanceTransform = EffectManager.GetAndActivatePooledEffect(chargeVfxPrefab, transform, inResetLocal: true)?.transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeToDisplayAttackCharging) * chargeDuration; + } + } + if (!chargeAnimPlayed) + { + PlayAnimation("Gesture, Additive", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + PlayAnimation("Gesture, Override", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + chargeAnimPlayed = true; + } + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + public override void Update() + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + + private void AuthorityFixedUpdate() + { + if (!base.inputBank.skill1.down && !base.inputBank.skill2.down) + { + if ((base.inputBank.skill2.justReleased || base.inputBank.skill1.justReleased) && CanOverheadSwing()) + { + outer.SetNextState(GetNextStateAuthority()); + } + else + { + HandleEarlyCancel(); + } + } + } + + private void HandleEarlyCancel() + { + if (cooldownTimestamp == -1f) + { + PlayAnimation("Gesture, Additive", "ChargeSwingExit"); + PlayAnimation("Gesture, Override", "ChargeSwingExit"); + cooldownTimestamp = Time.time; + } + } + + private bool CanOverheadSwing() + { + if (!(charge > minChargeToChargeAttack)) + { + return base.isGrounded; + } + return true; + } + + protected virtual bool ShouldKeepChargingAuthority() + { + return IsKeyDownAuthority(); + } + + protected virtual EntityState GetNextStateAuthority() + { + if (!base.isGrounded) + { + return new PreClubGroundSlam + { + charge = charge + }; + } + if (charge > minChargeToChargeAttack) + { + return new ChargedClubSwing + { + charge = charge, + chargeMetMinimumHold = (charge > minChargeToChargeAttack) + }; + } + return new OverheadClubSwing(); + } + + public override void OnExit() + { + if (clearOverrides) + { + skillOverrideData?.ClearOverrides(); + } + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + crosshairOverrideRequest?.Dispose(); + chargeVfxInstanceTransform = null; + } + if (!nonAuthority_AllowEarlyCancelAnimationToFinish) + { + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is ISkillOverrideHandoff skillOverrideHandoff) + { + skillOverrideHandoff.TransferSkillOverride(skillOverrideData); + clearOverrides = false; + if (!base.isAuthority && nextState is IdleSkillOverrideHandoff) + { + HandleEarlyCancel(); + nonAuthority_AllowEarlyCancelAnimationToFinish = true; + } + } + } + + public void TransferSkillOverride(SkillStateOverrideData skillOverrideData) + { + this.skillOverrideData = skillOverrideData; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFather.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFather.cs new file mode 100644 index 0000000..dccdf93 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFather.cs @@ -0,0 +1,235 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class LaserFather : BaseSkillState +{ + [SerializeField] + public float baseChargeDuration = 1f; + + [SerializeField] + public GameObject chargeCompletePrefab; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private Transform chargeVfxInstanceTransform; + + private int gauntlet; + + private uint soundID; + + public static float baseDuration = 3f; + + public static float laserMaxWidth = 0.2f; + + public static GameObject effectPrefab; + + public static GameObject laserPrefab; + + public static string attackSoundString; + + private float duration; + + private uint chargePlayID; + + private GameObject chargeEffect; + + private GameObject laserEffect; + + private LineRenderer laserLineComponent; + + private Vector3 laserDirection; + + private Vector3 visualEndPosition; + + private float flashTimer; + + private bool laserOn; + + private bool chargeAnimPlayed; + + private bool chargeFinished; + + private bool chargeStarted; + + private bool cancellingAttack; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration / attackSpeedStat; + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + chargePlayID = Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleLaser"); + if ((bool)transform) + { + if ((bool)effectPrefab) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)laserPrefab) + { + laserEffect = Object.Instantiate(laserPrefab, transform.position, transform.rotation); + laserEffect.transform.parent = transform; + laserLineComponent = laserEffect.GetComponent(); + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + flashTimer = 0f; + laserOn = true; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + LaserFatherCharged laserFatherCharged = nextState as LaserFatherCharged; + cancellingAttack = laserFatherCharged == null; + } + + public override void OnExit() + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + crosshairOverrideRequest?.Dispose(); + chargeVfxInstanceTransform = null; + } + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + if (cancellingAttack) + { + PlayAnimation("Gesture, Head, Additive", "Empty"); + PlayAnimation("Gesture, Head, Override", "Buffer Empty"); + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + AkSoundEngine.StopPlayingID(chargePlayID); + Util.PlaySound("Stop_falseson_skill4_laser_loop", base.gameObject); + Util.PlaySound("Stop_falseson_skill4_laser_charge_loop", base.gameObject); + base.OnExit(); + if ((bool)chargeEffect) + { + EntityState.Destroy(chargeEffect); + } + if ((bool)laserEffect) + { + EntityState.Destroy(laserEffect); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + AkSoundEngine.SetRTPCValueByPlayingID("charFalseSon_skill4_chargeAmount", charge * 100f, soundID); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeForChargedAttack && !chargeStarted) + { + chargeStarted = true; + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + PlayCrossfade("Gesture, Head, Additive", "LaserChargeIntro", "LaserChargeIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + PlayCrossfade("Gesture, Head, Override", "LaserChargeIntro", "LaserChargeIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + if (!(charge > 0.85f) || chargeFinished) + { + return; + } + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleLaser"); + if ((bool)transform) + { + chargeCompletePrefab = LegacyResourcesAPI.Load("FalseSon/FalseSonLaserChargeComplete"); + EffectManager.SpawnEffect(chargeCompletePrefab, new EffectData + { + origin = transform.transform.position, + scale = 1f + }, transmit: true); + chargeFinished = true; + } + } + } + + public override void Update() + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + + private void AuthorityFixedUpdate() + { + if (!ShouldKeepChargingAuthority()) + { + outer.SetNextState(GetNextStateAuthority()); + } + } + + protected virtual bool ShouldKeepChargingAuthority() + { + return IsKeyDownAuthority(); + } + + protected virtual EntityState GetNextStateAuthority() + { + if (charge < 0.175f) + { + charge = 0.175f; + } + return new LaserFatherCharged + { + charge = charge, + walkSpeedCoefficient = walkSpeedCoefficient + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFatherBurst.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFatherBurst.cs new file mode 100644 index 0000000..d0431ff --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFatherBurst.cs @@ -0,0 +1,174 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class LaserFatherBurst : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float blastRadius; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public static float laserTimerPercent = 0.12f; + + public Vector3 laserDirection; + + private float duration; + + private Ray modifiedAimRay; + + public float charge; + + private float maxSecondaryStock; + + private float secondaryStock; + + private Transform modelTransform; + + protected Transform muzzleTransform; + + private string targetMuzzle; + + private float rayDistance; + + private bool firedLaser; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Gesture, Override", "FireLaser", "FireLaser.playbackRate", duration, 0.1f); + PlayCrossfade("Gesture, Additive", "FireLaser", "FireLaser.playbackRate", duration, 0.1f); + maxSecondaryStock = base.skillLocator.GetSkill(SkillSlot.Secondary).maxStock; + secondaryStock = base.skillLocator.GetSkill(SkillSlot.Secondary).stock; + int num = (int)(maxSecondaryStock * 0.3f); + int num2 = (int)maxSecondaryStock - (int)secondaryStock; + if (num2 > 0) + { + if (num2 < num) + { + base.skillLocator.GetSkill(SkillSlot.Secondary).stock = base.skillLocator.GetSkill(SkillSlot.Secondary).maxStock; + } + else + { + base.skillLocator.GetSkill(SkillSlot.Secondary).stock = base.skillLocator.GetSkill(SkillSlot.Secondary).stock + num; + } + } + } + + public void FireBurstLaser() + { + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild("MuzzleLaser"); + } + } + rayDistance = 1000f; + Ray aimRay = GetAimRay(); + Vector3 position = muzzleTransform.transform.parent.position; + Vector3 point = aimRay.GetPoint(rayDistance); + laserDirection = point - position; + modifiedAimRay = GetAimRay(); + modifiedAimRay.direction = laserDirection; + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref modifiedAimRay, rayDistance, base.gameObject); + GetModelAnimator(); + Util.PlaySound(attackSoundString, base.gameObject); + targetMuzzle = "MuzzleLaser"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (!base.isAuthority) + { + return; + } + rayDistance = 200f; + Vector3 vector = modifiedAimRay.origin + modifiedAimRay.direction * rayDistance; + if (Physics.Raycast(modifiedAimRay, out var hitInfo, rayDistance, LayerIndex.CommonMasks.laser)) + { + vector = hitInfo.point; + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = force * 0.2f; + blastAttack.position = vector; + blastAttack.radius = blastRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.SweetSpot; + blastAttack.bonusForce = force * modifiedAimRay.direction; + blastAttack.Fire(); + _ = modifiedAimRay.origin; + if (!modelTransform) + { + return; + } + ChildLocator component2 = modelTransform.GetComponent(); + if ((bool)component2) + { + int childIndex = component2.FindChildIndex(targetMuzzle); + if ((bool)tracerEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = vector, + start = modifiedAimRay.origin + }; + effectData.SetChildLocatorTransformReference(base.gameObject, childIndex); + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + EffectManager.SpawnEffect(hitEffectPrefab, effectData, transmit: true); + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration * laserTimerPercent && !firedLaser) + { + firedLaser = true; + FireBurstLaser(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFatherCharged.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFatherCharged.cs new file mode 100644 index 0000000..0f21847 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LaserFatherCharged.cs @@ -0,0 +1,275 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSon; + +public class LaserFatherCharged : BaseState +{ + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject laserPrefab; + + public static string playAttackSoundString; + + public static string playLoopSoundString; + + public static string stopLoopSoundString; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float fireFrequency; + + public static float maxDistance; + + public static float minimumDuration; + + public static float maximumDuration; + + public static float lockOnAngle; + + public static float procCoefficientPerTick; + + private HurtBox lockedOnHurtBox; + + private float fireStopwatch; + + private float stopwatch; + + private float refillSecondaryStopwatch; + + private float maxSecondaryStock; + + private float secondaryStock; + + private Ray aimRay; + + private Transform modelTransform; + + private GameObject laserEffect; + + private ChildLocator laserChildLocator; + + private Transform laserEffectEnd; + + public float charge; + + protected Transform muzzleTransform; + + private float bonusDuration; + + protected CameraTargetParams.AimRequest aimRequest; + + public static int abilityAimType; + + private float duration; + + public float walkSpeedCoefficient = 1f; + + private int lunarSpikeCount; + + public static event Action laserTracking; + + public override void OnEnter() + { + base.OnEnter(); + duration = maximumDuration; + aimRequest = base.cameraTargetParams.RequestAimType((CameraTargetParams.AimType)abilityAimType); + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + FalseSonController component = GetComponent(); + if ((bool)component) + { + lunarSpikeCount = component.GetTotalSpikeCount(); + } + else + { + lunarSpikeCount = 0; + } + Util.PlaySound("Play_falseson_skill4_laser_start", base.gameObject); + PlayCrossfade("Gesture, Head, Override", "FireLaserLoop", 0.25f); + PlayCrossfade("Gesture, Head, Additive", "FireLaserLoop", 0.25f); + aimRay = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref aimRay, maxDistance, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component2 = modelTransform.GetComponent(); + if ((bool)component2) + { + muzzleTransform = component2.FindChild("MuzzleLaser"); + if ((bool)muzzleTransform && (bool)laserPrefab) + { + laserEffect = UnityEngine.Object.Instantiate(laserPrefab, muzzleTransform.position, muzzleTransform.rotation); + laserEffect.transform.parent = muzzleTransform; + laserChildLocator = laserEffect.GetComponent(); + laserEffectEnd = laserChildLocator.FindChild("LaserEnd"); + } + } + } + bonusDuration = 0f; + for (int i = 1; i <= lunarSpikeCount; i++) + { + bonusDuration += 1f / (0.5f * (float)i + 1f); + } + if (bonusDuration < 0f) + { + bonusDuration = 0f; + } + duration += bonusDuration; + base.characterBody.SetAimTimer(duration); + float num = base.characterBody.attackSpeed - base.characterBody.baseAttackSpeed; + fireFrequency += num * 0.3f; + maxSecondaryStock = base.skillLocator.GetSkill(SkillSlot.Secondary).maxStock; + secondaryStock = base.skillLocator.GetSkill(SkillSlot.Secondary).maxStock; + LaserFatherCharged.laserTracking?.Invoke(duration); + } + + public override void OnExit() + { + aimRequest?.Dispose(); + if ((bool)laserEffect) + { + LaserFatherCharged.laserTracking?.Invoke(0f); + EntityState.Destroy(laserEffect); + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + base.characterBody.SetAimTimer(2f); + Util.PlaySound("Stop_falseson_skill4_laser_loop", base.gameObject); + Util.PlaySound("Stop_falseson_skill4_laser_charge_loop", base.gameObject); + Util.PlaySound("Play_falseson_skill4_laser_end", base.gameObject); + PlayAnimation("Gesture, Head, Override", "FireLaserLoopEnd"); + PlayAnimation("Gesture, Head, Additive", "FireLaserLoopEnd"); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + fireStopwatch += deltaTime; + stopwatch += deltaTime; + refillSecondaryStopwatch += deltaTime; + if (refillSecondaryStopwatch > 1f) + { + maxSecondaryStock = base.skillLocator.GetSkill(SkillSlot.Secondary).maxStock; + secondaryStock = base.skillLocator.GetSkill(SkillSlot.Secondary).stock; + if (secondaryStock < maxSecondaryStock) + { + base.skillLocator.GetSkill(SkillSlot.Secondary).stock++; + refillSecondaryStopwatch = 0f; + } + } + aimRay = GetAimRay(); + Vector3 vector = aimRay.origin; + if ((bool)muzzleTransform) + { + vector = muzzleTransform.position; + } + Vector3 vector2; + if ((bool)lockedOnHurtBox) + { + vector2 = lockedOnHurtBox.transform.position; + } + else + { + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref aimRay, maxDistance, base.gameObject); + vector2 = ((!Util.CharacterRaycast(base.gameObject, aimRay, out var hitInfo, maxDistance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) ? aimRay.GetPoint(maxDistance) : hitInfo.point); + } + Ray ray = new Ray(vector, vector2 - vector); + bool flag = false; + if ((bool)laserEffect && (bool)laserChildLocator) + { + if (Util.CharacterRaycast(base.gameObject, ray, out var hitInfo2, (vector2 - vector).magnitude, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + vector2 = hitInfo2.point; + if (Util.CharacterRaycast(base.gameObject, new Ray(vector2 - ray.direction * 0.1f, -ray.direction), out var _, hitInfo2.distance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + vector2 = ray.GetPoint(0.1f); + flag = true; + } + } + laserEffect.transform.rotation = Util.QuaternionSafeLookRotation(vector2 - vector); + laserEffectEnd.transform.position = vector2; + } + if (fireStopwatch > 1f / fireFrequency) + { + string targetMuzzle = "MuzzleLaser"; + if (!flag) + { + FireBullet(modelTransform, ray, targetMuzzle, (vector2 - ray.origin).magnitude + 0.1f); + } + fireStopwatch -= 1f / fireFrequency; + } + if (base.isAuthority && stopwatch > duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + private void FireBullet(Transform modelTransform, Ray aimRay, string targetMuzzle, float maxDistance) + { + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + if (charge > 0.85f) + { + charge = 1f; + } + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat * charge; + bulletAttack.force = force; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.procCoefficient = procCoefficientPerTick; + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 1f; + bulletAttack.maxDistance = maxDistance; + bulletAttack.Fire(); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(HurtBoxReference.FromHurtBox(lockedOnHurtBox)); + writer.Write(stopwatch); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + HurtBoxReference hurtBoxReference = reader.ReadHurtBoxReference(); + stopwatch = reader.ReadSingle(); + lockedOnHurtBox = hurtBoxReference.ResolveGameObject()?.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LunarSpikes.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LunarSpikes.cs new file mode 100644 index 0000000..c05dad7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LunarSpikes.cs @@ -0,0 +1,115 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class LunarSpikes : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force = 20f; + + public static float attackSpeedAltAnimationThreshold; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float attackSoundPitch; + + public static float bloom; + + private float duration; + + private bool hasFiredSpike; + + private string muzzleString; + + private Transform muzzleTransform; + + private Animator animator; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSoundPitch); + base.characterBody.SetAimTimer(2f); + animator = GetModelAnimator(); + if ((bool)animator) + { + childLocator = animator.GetComponent(); + } + muzzleString = "MuzzleRight"; + if (attackSpeedStat < attackSpeedAltAnimationThreshold) + { + PlayCrossfade("Gesture, Additive", "FireLunarSpike", "LunarSpike.playbackRate", duration, 0.1f); + PlayCrossfade("Gesture, Override", "FireLunarSpike", "LunarSpike.playbackRate", duration, 0.1f); + FireLunarSpike(); + } + else + { + PlayAnimation("Gesture, Override", "HoldGauntletsUp", "LunarSpike.playbackRate", duration); + FireLunarSpike(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireLunarSpike() + { + if (!hasFiredSpike) + { + base.characterBody.AddSpreadBloom(bloom); + hasFiredSpike = true; + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild(muzzleString); + } + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damageCoefficient * damageStat, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Void); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LunarSpikesShotgun.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LunarSpikesShotgun.cs new file mode 100644 index 0000000..5d69ae1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/LunarSpikesShotgun.cs @@ -0,0 +1,115 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.FalseSon; + +public class LunarSpikesShotgun : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force = 20f; + + public static float attackSpeedAltAnimationThreshold; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float attackSoundPitch; + + public static float bloom; + + private float duration; + + private bool hasFiredSpike; + + private string muzzleString; + + private Transform muzzleTransform; + + private Animator animator; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSoundPitch); + base.characterBody.SetAimTimer(2f); + animator = GetModelAnimator(); + if ((bool)animator) + { + childLocator = animator.GetComponent(); + } + muzzleString = "MuzzleRight"; + if (attackSpeedStat < attackSpeedAltAnimationThreshold) + { + PlayCrossfade("Gesture, Additive", "FireLunarSpike", "LunarSpike.playbackRate", duration, 0.1f); + PlayCrossfade("Gesture, Override", "FireLunarSpike", "LunarSpike.playbackRate", duration, 0.1f); + FireLunarSpike(); + } + else + { + PlayAnimation("Gesture, Override", "HoldGauntletsUp", "LunarSpike.playbackRate", duration); + FireLunarSpike(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireLunarSpike() + { + if (!hasFiredSpike) + { + base.characterBody.AddSpreadBloom(bloom); + hasFiredSpike = true; + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild(muzzleString); + } + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damageCoefficient * damageStat, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Void); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/OverheadClubSwing.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/OverheadClubSwing.cs new file mode 100644 index 0000000..7ed6af5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/OverheadClubSwing.cs @@ -0,0 +1,14 @@ +namespace EntityStates.FalseSon; + +public class OverheadClubSwing : BasicMeleeAttack +{ + protected override void PlayAnimation() + { + PlayAnimation("FullBody, Override", "OverheadSwing", "ChargeSwing.playbackRate", duration); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/PreClubGroundSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/PreClubGroundSlam.cs new file mode 100644 index 0000000..ceccb11 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/PreClubGroundSlam.cs @@ -0,0 +1,68 @@ +using RoR2; + +namespace EntityStates.FalseSon; + +public class PreClubGroundSlam : BaseState +{ + public float charge; + + public static float baseDuration; + + public static string enterSoundString; + + public static float upwardVelocity; + + private float duration; + + private bool forceAnimWrapUp = true; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Body", "PreGroundSlam", "GroundSlam.playbackRate", duration); + Util.PlaySound(enterSoundString, base.gameObject); + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.disableAirControlUntilCollision = false; + base.characterMotor.velocity.y = upwardVelocity; + base.characterBody.bodyFlags |= CharacterBody.BodyFlags.IgnoreFallDamage; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterMotor.moveDirection = base.inputBank.moveVector; + base.characterBody.SetSpreadBloom(charge); + if (base.fixedAge > duration) + { + forceAnimWrapUp = false; + outer.SetNextState(new ClubGroundSlam + { + charge = charge + }); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + public override void ModifyNextState(EntityState nextState) + { + ClubGroundSlam clubGroundSlam = nextState as ClubGroundSlam; + forceAnimWrapUp = clubGroundSlam == null; + } + + public override void OnExit() + { + base.OnExit(); + if (forceAnimWrapUp) + { + PlayAnimation("Gesture, Override", "Empty"); + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Body", "Idle"); + base.characterBody.bodyFlags &= ~CharacterBody.BodyFlags.IgnoreFallDamage; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/StepBrothers.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/StepBrothers.cs new file mode 100644 index 0000000..da42eb4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/StepBrothers.cs @@ -0,0 +1,193 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSon; + +public class StepBrothers : BaseState +{ + private Transform modelTransform; + + public static GameObject dashPrefab; + + public static float smallHopVelocity; + + public static float dashPrepDuration; + + public static float dashDuration = 0.3f; + + public static float speedCoefficient = 25f; + + public static string beginSoundString; + + public static float damageCoefficient; + + public static float procCoefficient; + + public static GameObject hitEffectPrefab; + + public static float hitPauseDuration; + + private float stopwatch; + + private Vector3 dashVector = Vector3.zero; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private OverlapAttack overlapAttack; + + private ChildLocator childLocator; + + private bool isDashing; + + private bool inHitPause; + + private float hitPauseTimer; + + private CameraTargetParams.AimRequest aimRequest; + + private CharacterBody survivorBody; + + public static GameObject explosionEffect; + + public BlastAttack explosionAttack; + + private int originalLayer; + + public bool hasHit { get; private set; } + + public int dashIndex { private get; set; } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + survivorBody = base.gameObject.GetComponent(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + childLocator = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + _ = (bool)childLocator; + } + PlayAnimation("FullBody, Override", "StepBrothersPrep", "StepBrothersPrep.playbackRate", dashPrepDuration); + dashVector = base.inputBank.aimDirection; + overlapAttack = InitMeleeOverlap(0f, hitEffectPrefab, modelTransform, "StepBrothers"); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + } + + private void CreateDashEffect() + { + Transform transform = childLocator.FindChild("DashCenter"); + if ((bool)transform && (bool)dashPrefab) + { + Object.Instantiate(dashPrefab, transform.position, Util.QuaternionSafeLookRotation(dashVector), transform); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterDirection.forward = dashVector; + if (stopwatch > dashPrepDuration / attackSpeedStat && !isDashing) + { + isDashing = true; + dashVector = base.inputBank.aimDirection; + CreateDashEffect(); + PlayCrossfade("FullBody, Override", "StepBrothersLoop", 0.1f); + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + } + if (!isDashing) + { + stopwatch += GetDeltaTime(); + } + else if (base.isAuthority) + { + base.characterMotor.velocity = Vector3.zero; + if (!inHitPause) + { + bool num = overlapAttack.Fire(); + stopwatch += GetDeltaTime(); + if (num) + { + Vector3 position = base.gameObject.transform.position; + Object.Instantiate(explosionEffect, position, Quaternion.identity); + explosionAttack = new BlastAttack(); + explosionAttack.attacker = base.gameObject; + explosionAttack.inflictor = base.gameObject; + explosionAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + explosionAttack.baseDamage = damageStat * damageCoefficient; + explosionAttack.position = position; + explosionAttack.radius = 20f; + explosionAttack.Fire(); + if (!hasHit) + { + hasHit = true; + } + inHitPause = true; + hitPauseTimer = hitPauseDuration / attackSpeedStat; + } + base.characterMotor.rootMotion += dashVector * moveSpeedStat * speedCoefficient * GetDeltaTime(); + } + else + { + hitPauseTimer -= GetDeltaTime(); + if (hitPauseTimer < 0f) + { + inHitPause = false; + } + } + } + if (stopwatch >= dashDuration + dashPrepDuration / attackSpeedStat && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + _ = base.isAuthority; + aimRequest?.Dispose(); + _ = (bool)childLocator; + PlayAnimation("FullBody, Override", "StepBrothersLoopExit"); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)dashIndex); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dashIndex = reader.ReadByte(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSon/TheTamperedHeart.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/TheTamperedHeart.cs new file mode 100644 index 0000000..5e84c99 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSon/TheTamperedHeart.cs @@ -0,0 +1,8 @@ +namespace EntityStates.FalseSon; + +public class TheTamperedHeart : BaseState +{ + public override void OnEnter() + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/BrokenCrystalDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/BrokenCrystalDeathState.cs new file mode 100644 index 0000000..27ecf1f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/BrokenCrystalDeathState.cs @@ -0,0 +1,69 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class BrokenCrystalDeathState : GenericCharacterDeath +{ + public static float duration = 3f; + + public static GameObject deathEffectPrefab; + + public float vfxSize = 8f; + + private bool playedSFX; + + private bool _shouldAutoDestroy; + + protected override bool shouldAutoDestroy => _shouldAutoDestroy; + + public override void OnEnter() + { + base.OnEnter(); + } + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + MeridianEventTriggerInteraction.instance.musicPhaseTwo.SetActive(value: false); + MeridianEventTriggerInteraction.instance.musicPhaseThree.SetActive(value: true); + PlayAnimation("FullBody, Override", "Phase2Death", "StepBrothersPrep.playbackRate", duration); + } + + public override void FixedUpdate() + { + if (base.fixedAge >= 2f && !playedSFX) + { + Util.PlaySound("Play_boss_falseson_phaseTransition_kneel", base.characterBody.gameObject); + Util.PlaySound("Play_boss_falseson_VO_anger", base.characterBody.gameObject); + playedSFX = true; + } + if (!_shouldAutoDestroy && NetworkServer.active && (double)base.fixedAge >= (double)duration + 0.5) + { + _shouldAutoDestroy = true; + EffectManager.SpawnEffect(deathEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition, + scale = vfxSize + }, transmit: true); + } + base.FixedUpdate(); + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + MeridianEventTriggerInteraction.FSBFPhaseBaseState.readyToSpawnNextBossBody = true; + DestroyBodyServer(); + } + + private void DestroyBodyServer() + { + if (NetworkServer.active) + { + OnPreDestroyBodyServer(); + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/ClubForsakenBoss.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/ClubForsakenBoss.cs new file mode 100644 index 0000000..2466979 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/ClubForsakenBoss.cs @@ -0,0 +1,125 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class ClubForsakenBoss : BaseSkillState +{ + [SerializeField] + public float baseChargeDuration = 1f; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private Transform chargeVfxInstanceTransform; + + private int gauntlet; + + private uint soundID; + + private bool chargeAnimPlayed; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration; + Util.PlaySound(enterSFXString, base.gameObject); + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnExit() + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + crosshairOverrideRequest?.Dispose(); + chargeVfxInstanceTransform = null; + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + AkSoundEngine.SetRTPCValueByPlayingID("loaderShift_chargeAmount", charge * 100f, soundID); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeForChargedAttack && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + if ((bool)crosshairOverridePrefab && crosshairOverrideRequest == null) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform) + { + chargeVfxInstanceTransform = Object.Instantiate(chargeVfxPrefab, transform).transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeForChargedAttack) * chargeDuration; + } + } + if (!chargeAnimPlayed) + { + PlayCrossfade("Gesture, Additive", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + PlayCrossfade("Gesture, Override", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", 0.2f * chargeDuration, 0.1f); + chargeAnimPlayed = true; + } + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + public override void Update() + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + + private void AuthorityFixedUpdate() + { + ShouldKeepChargingAuthority(); + } + + protected virtual bool ShouldKeepChargingAuthority() + { + return IsKeyDownAuthority(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CorruptedPaths.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CorruptedPaths.cs new file mode 100644 index 0000000..e439b48 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CorruptedPaths.cs @@ -0,0 +1,103 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class CorruptedPaths : BaseCharacterMain +{ + [SerializeField] + public float baseDuration; + + public float charge; + + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static string enterSoundString; + + public static Vector3 blastBonusForce; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static GameObject fistEffectPrefab; + + public static GameObject swingEffectPrefab; + + private GameObject leftFistEffectInstance; + + private GameObject rightFistEffectInstance; + + private GameObject swingEffectInstance; + + private bool detonateNextFrame; + + public override void OnEnter() + { + base.OnEnter(); + baseDuration /= attackSpeedStat; + PlayAnimation("FullBody, Override", "ChargeSwing", "ChargeSwing.playbackRate", baseDuration); + Util.PlaySound(enterSoundString, base.gameObject); + swingEffectInstance = Object.Instantiate(swingEffectPrefab, FindModelChild("OverHeadSwingPoint")); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= minimumDuration) + { + DetonateAuthority(); + if (base.characterBody.GetBuffCount(DLC2Content.Buffs.CorruptionFesters) == 0) + { + outer.SetNextState(new CorruptedPathsDash()); + } + else + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 position = FindModelChild("ClubExplosionPoint").transform.position; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = position, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * (blastDamageCoefficient * charge) + (base.characterBody.maxHealth - (base.characterBody.baseMaxHealth + base.characterBody.levelMaxHealth * (float)((int)base.characterBody.level - 1))) * 0.01f, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = position, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CorruptedPathsDash.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CorruptedPathsDash.cs new file mode 100644 index 0000000..1d96107 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CorruptedPathsDash.cs @@ -0,0 +1,216 @@ +using RoR2; +using RoR2.CharacterAI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class CorruptedPathsDash : BaseState +{ + private Transform modelTransform; + + public static GameObject dashPrefab; + + public static float smallHopVelocity = 0.35f; + + public static float dashPrepDuration = 0.8f; + + public static float dashDuration = 0.05f; + + public static float speedCoefficient = 15f; + + public static float gapToEnemy = 0f; + + public static string beginSoundString; + + public static string endSoundString; + + public static float damageCoefficient = 2f; + + public static float procCoefficient; + + public static GameObject hitEffectPrefab; + + public static float hitPauseDuration; + + private float stopwatch; + + private Vector3 dashVector = Vector3.zero; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private OverlapAttack overlapAttack; + + private ChildLocator childLocator; + + private bool isDashing; + + private bool inHitPause; + + private float hitPauseTimer; + + private CameraTargetParams.AimRequest aimRequest; + + private CharacterBody survivorBody; + + public static GameObject explosionEffect; + + public BlastAttack explosionAttack; + + private float maxHealth; + + private int originalLayer; + + public bool hasHit { get; private set; } + + public int dashIndex { private get; set; } + + public override void OnEnter() + { + base.OnEnter(); + dashDuration = Vector3.Distance(base.characterBody.master.GetComponent().currentEnemy.characterBody.transform.position, base.transform.position) * 0.1f / speedCoefficient - gapToEnemy; + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + survivorBody = base.gameObject.GetComponent(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + childLocator = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + _ = (bool)childLocator; + } + SmallHop(base.characterMotor, smallHopVelocity); + PlayAnimation("FullBody, Override", "StepBrothersPrep", "StepBrothersPrep.playbackRate", dashPrepDuration); + dashVector = base.inputBank.aimDirection; + overlapAttack = InitMeleeOverlap(0f, hitEffectPrefab, modelTransform, "StepBrothers"); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + } + + private void CreateDashEffect() + { + Transform transform = childLocator.FindChild("DashCenter"); + if ((bool)transform && (bool)dashPrefab) + { + Object.Instantiate(dashPrefab, transform.position, Util.QuaternionSafeLookRotation(dashVector), transform); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterDirection.forward = dashVector; + if (stopwatch > dashPrepDuration && !isDashing) + { + isDashing = true; + dashVector = base.inputBank.aimDirection; + CreateDashEffect(); + PlayCrossfade("FullBody, Override", "StepBrothersLoop", 0.1f); + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + } + if (!isDashing) + { + stopwatch += GetDeltaTime(); + } + else if (base.isAuthority) + { + base.characterMotor.velocity = Vector3.zero; + if (!inHitPause) + { + bool num = overlapAttack.Fire(); + stopwatch += GetDeltaTime(); + if (num) + { + Vector3 position = base.gameObject.transform.position; + EffectManager.SpawnEffect(explosionEffect, new EffectData + { + origin = position, + scale = 1f + }, transmit: true); + explosionAttack = new BlastAttack(); + explosionAttack.attacker = base.gameObject; + explosionAttack.inflictor = base.gameObject; + explosionAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + explosionAttack.baseDamage = damageStat * damageCoefficient; + explosionAttack.position = position; + explosionAttack.radius = 20f; + explosionAttack.Fire(); + if (!hasHit) + { + hasHit = true; + } + inHitPause = true; + hitPauseTimer = hitPauseDuration / attackSpeedStat; + } + base.characterMotor.rootMotion += dashVector * moveSpeedStat * speedCoefficient * GetDeltaTime(); + } + else + { + hitPauseTimer -= GetDeltaTime(); + if (hitPauseTimer < 0f) + { + inHitPause = false; + } + } + } + if (stopwatch >= dashDuration + dashPrepDuration && base.isAuthority) + { + outer.SetNextState(GetNextStateAuthority()); + } + } + + public override void OnExit() + { + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + Util.PlaySound(endSoundString, base.gameObject); + if (base.isAuthority) + { + base.characterMotor.velocity *= -0.3f; + SmallHop(base.characterMotor, smallHopVelocity); + } + aimRequest?.Dispose(); + _ = (bool)childLocator; + PlayAnimation("FullBody, Override", "StepBrothersLoopExit"); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)dashIndex); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dashIndex = reader.ReadByte(); + } + + protected virtual EntityState GetNextStateAuthority() + { + return new FissureSlam(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CrystalDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CrystalDeathState.cs new file mode 100644 index 0000000..8803b0c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/CrystalDeathState.cs @@ -0,0 +1,70 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class CrystalDeathState : GenericCharacterDeath +{ + public static GameObject deathEffectPrefab; + + public static float duration = 3f; + + public float vfxSize = 8f; + + private bool playedSFX; + + private bool _shouldAutoDestroy; + + protected override bool shouldAutoDestroy => _shouldAutoDestroy; + + public override void OnEnter() + { + base.OnEnter(); + } + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayAnimation("FullBody, Override", "Phase1Death", "StepBrothersPrep.playbackRate", duration); + MeridianEventTriggerInteraction.instance.musicPhaseOne.SetActive(value: false); + MeridianEventTriggerInteraction.instance.musicPhaseTwo.SetActive(value: true); + } + + public override void FixedUpdate() + { + if (base.fixedAge >= 2f && !playedSFX) + { + Util.PlaySound("Play_boss_falseson_phaseTransition_kneel", base.characterBody.gameObject); + Util.PlaySound("Play_boss_falseson_VO_groan", base.gameObject); + playedSFX = true; + } + if (!_shouldAutoDestroy && NetworkServer.active && base.fixedAge >= duration + 0.5f) + { + EffectManager.SpawnEffect(deathEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition, + scale = vfxSize + }, transmit: true); + _shouldAutoDestroy = true; + } + base.FixedUpdate(); + } + + public override void OnExit() + { + DestroyBodyAsapServer(); + DestroyModel(); + base.OnExit(); + MeridianEventTriggerInteraction.FSBFPhaseBaseState.readyToSpawnNextBossBody = true; + DestroyBodyServer(); + } + + private void DestroyBodyServer() + { + if (NetworkServer.active) + { + OnPreDestroyBodyServer(); + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FalseSonBossGenericStateWithSwing.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FalseSonBossGenericStateWithSwing.cs new file mode 100644 index 0000000..4198307 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FalseSonBossGenericStateWithSwing.cs @@ -0,0 +1,46 @@ +namespace EntityStates.FalseSonBoss; + +public class FalseSonBossGenericStateWithSwing : GenericCharacterMain +{ + private bool transitioningToMeleeSwingState; + + public override void OnEnter() + { + base.OnEnter(); + transitioningToMeleeSwingState = false; + } + + public override void Update() + { + if (base.characterBody == null || base.characterBody.coreTransform == null) + { + if (outer != null) + { + outer.SetNextStateToMain(); + } + return; + } + base.Update(); + if (!transitioningToMeleeSwingState) + { + FalseSonBossStateHelper.TrySwitchToMeleeSwing(ref transitioningToMeleeSwingState, base.characterBody.coreTransform, base.characterDirection.forward, null, outer); + } + } + + public override void FixedUpdate() + { + if (!transitioningToMeleeSwingState) + { + base.FixedUpdate(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (transitioningToMeleeSwingState) + { + return InterruptPriority.Frozen; + } + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FalseSonBossStateHelper.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FalseSonBossStateHelper.cs new file mode 100644 index 0000000..f97550c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FalseSonBossStateHelper.cs @@ -0,0 +1,97 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public static class FalseSonBossStateHelper +{ + private static int hitLimit = 2; + + private static float coolDownDuration = 2f; + + private static int hitCount = 0; + + private static float coolDownTimeStamp = -3f; + + private static float maxDistanceSquared = 225f; + + private static bool CheckPlayerOrMinionsForProximity(PlayerCharacterMasterController playerController, Vector3 playerPosition, Vector3 aimDirection, Vector3 bossPosition) + { + Vector3 vectorToCharacter; + if (CharacterIsInFrontOfUs(playerPosition)) + { + return true; + } + MinionOwnership.MinionGroup minionGroup = MinionOwnership.MinionGroup.FindGroup(playerController.master.netId); + if (minionGroup == null || minionGroup.memberCount < 1) + { + return false; + } + MinionOwnership[] members = minionGroup.members; + foreach (MinionOwnership minionOwnership in members) + { + if (!(minionOwnership == null)) + { + Vector3 value = (minionOwnership.GetComponent()?.GetBody()?.corePosition).Value; + if (value != Vector3.zero && CharacterIsInFrontOfUs(value)) + { + return true; + } + } + } + return false; + bool CharacterIsInFrontOfUs(Vector3 position) + { + vectorToCharacter = position - bossPosition; + if (Vector3.SqrMagnitude(vectorToCharacter) > maxDistanceSquared) + { + return false; + } + if (Vector3.Dot(vectorToCharacter.normalized, aimDirection) <= 0f) + { + return false; + } + return true; + } + } + + public static bool TrySwitchToMeleeSwing(ref bool stateAborted, Transform bossTransform, Vector3 aimDirection, GenericSkill previousSkill, EntityStateMachine outer) + { + if (bossTransform == null) + { + return false; + } + if (PlatformSystems.networkManager.serverFixedTime - coolDownTimeStamp < coolDownDuration) + { + return false; + } + stateAborted = false; + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + if (!(instance == null)) + { + CharacterBody body = instance.master.GetBody(); + if (!(body == null) && CheckPlayerOrMinionsForProximity(instance, body.corePosition, aimDirection, bossTransform.position)) + { + stateAborted = true; + break; + } + } + } + if (stateAborted) + { + outer.SetNextState(new SwatAwayPlayersWindup()); + if ((bool)previousSkill) + { + previousSkill.Reset(); + } + hitCount++; + if (hitCount >= hitLimit) + { + coolDownTimeStamp = PlatformSystems.networkManager.serverFixedTime; + hitCount = 0; + } + } + return stateAborted; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FissureSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FissureSlam.cs new file mode 100644 index 0000000..3195023 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FissureSlam.cs @@ -0,0 +1,241 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Navigation; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class FissureSlam : BaseCharacterMain +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public int totalFissures = 5; + + [SerializeField] + public float delayBetweenFissures = 0.001f; + + public float charge; + + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static string enterSoundString; + + public static Vector3 blastBonusForce; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static GameObject fistEffectPrefab; + + public static GameObject swingEffectPrefab; + + public static GameObject fissureSlamObject; + + private GameObject leftFistEffectInstance; + + private GameObject rightFistEffectInstance; + + private GameObject swingEffectInstance; + + private bool detonateNextFrame; + + private bool amServer; + + private bool slamComplete; + + private float fissureExplosionDelay = 0.7f; + + private float fissureExplosionTimer; + + private NodeGraph nodeGraph; + + private List possibleNodesToTarget; + + private List playersToTarget; + + private List fissurePositions; + + private int totalFissuresFired; + + private float timeToGenerateNextFissure; + + public static GameObject crackWarningEffectPrefab; + + public static GameObject fissureExplosionEffectPrefab; + + public static GameObject pillarProjectilePrefab; + + private bool stateAborted; + + public override void OnEnter() + { + base.OnEnter(); + amServer = NetworkServer.active; + baseDuration /= attackSpeedStat; + PlayAnimation("FullBody, Override", "ChargeSwing", "ChargeSwing.playbackRate", baseDuration); + Util.PlaySound(enterSoundString, base.gameObject); + leftFistEffectInstance = Object.Instantiate(fistEffectPrefab, FindModelChild("HandR")); + rightFistEffectInstance = Object.Instantiate(fistEffectPrefab, FindModelChild("HandL")); + swingEffectInstance = Object.Instantiate(swingEffectPrefab, FindModelChild("OverHeadSwingPoint")); + nodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + possibleNodesToTarget = nodeGraph.FindNodesInRange(base.characterBody.corePosition, 0f, 30f, HullMask.Human); + playersToTarget = new List(); + fissurePositions = new List(); + totalFissuresFired = 0; + timeToGenerateNextFissure = 0f; + if (!amServer) + { + return; + } + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + if (!(instance == null) && !(instance.master.GetBodyObject() == null)) + { + playersToTarget.Add(instance.master.GetBodyObject()); + } + } + Util.ShuffleList(playersToTarget); + RaycastToFindGroundPointOfNextPlayer(); + } + + private void RaycastToFindGroundPointOfNextPlayer() + { + if (fissurePositions.Count >= totalFissures) + { + return; + } + if (fissurePositions.Count < playersToTarget.Count && playersToTarget.Count > 0) + { + if (Physics.Raycast(new Ray(playersToTarget[fissurePositions.Count].transform.position + Vector3.up * 1f, Vector3.down), out var hitInfo, 200f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + fissurePositions.Add(hitInfo.point); + } + else + { + if (possibleNodesToTarget.Count < 1) + { + return; + } + int index = Random.Range(0, possibleNodesToTarget.Count); + nodeGraph.GetNodePosition(possibleNodesToTarget[index], out var position); + fissurePositions.Add(position); + possibleNodesToTarget.RemoveAt(index); + } + } + if (fissurePositions.Count >= playersToTarget.Count) + { + FillRemainingFissurePositions(); + } + } + + private void FillRemainingFissurePositions() + { + if (fissurePositions.Count >= totalFissures) + { + return; + } + int num = Mathf.Max(totalFissures - fissurePositions.Count, 0); + for (int i = 0; i < num; i++) + { + if (possibleNodesToTarget.Count < 1) + { + break; + } + int index = Random.Range(0, possibleNodesToTarget.Count); + nodeGraph.GetNodePosition(possibleNodesToTarget[index], out var position); + fissurePositions.Add(position); + possibleNodesToTarget.RemoveAt(index); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (stateAborted) + { + return; + } + RaycastToFindGroundPointOfNextPlayer(); + if (!slamComplete && base.fixedAge >= baseDuration - baseDuration * 0.8f && amServer) + { + DetonateAuthority(); + slamComplete = true; + FillRemainingFissurePositions(); + int num = Mathf.Min(totalFissures, fissurePositions.Count); + for (int i = 0; i < num; i++) + { + EffectManager.SpawnEffect(crackWarningEffectPrefab, new EffectData + { + origin = fissurePositions[i] + Vector3.up * 0.01f + }, transmit: true); + } + } + if (!slamComplete || !amServer) + { + return; + } + fissureExplosionTimer += Time.deltaTime; + if (fissureExplosionTimer > fissureExplosionDelay) + { + int num2 = Mathf.Min(totalFissures, fissurePositions.Count); + for (int j = 0; j < num2; j++) + { + ProjectileManager.instance.FireProjectile(pillarProjectilePrefab, fissurePositions[j], Quaternion.identity, base.gameObject, base.characterBody.damage * (blastDamageCoefficient * 0.2f), 0f, Util.CheckRoll(base.characterBody.crit, base.characterBody.master)); + } + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (!stateAborted) + { + EntityState.Destroy(leftFistEffectInstance); + EntityState.Destroy(rightFistEffectInstance); + base.OnExit(); + } + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 position = FindModelChild("ClubExplosionPoint").transform.position; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = position, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius + 3f, + position = position, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FissureSlamWindup.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FissureSlamWindup.cs new file mode 100644 index 0000000..1c7d212 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/FissureSlamWindup.cs @@ -0,0 +1,130 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class FissureSlamWindup : BaseSkillState +{ + [SerializeField] + public float baseChargeDuration = 1f; + + [SerializeField] + public float chargeThreshold = 3f; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private int gauntlet; + + private uint soundID; + + private Transform chargeVfxInstanceTransform; + + private bool chargeAnimPlayed; + + private bool stateAborted; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = 0.5f; + Util.PlaySound(enterSFXString, base.gameObject); + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + if (base.characterBody.GetBuffCount(DLC2Content.Buffs.WeakenedBeating) > 0) + { + charge = 0.5f; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnExit() + { + if (!stateAborted) + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + chargeVfxInstanceTransform = null; + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + } + + public override void FixedUpdate() + { + if (stateAborted) + { + return; + } + base.FixedUpdate(); + charge += Time.deltaTime; + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge <= 3f && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform) + { + chargeVfxInstanceTransform = Object.Instantiate(chargeVfxPrefab, transform).transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeForChargedAttack) * chargeDuration; + } + } + if (!chargeAnimPlayed) + { + PlayCrossfade("Gesture, Additive", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", chargeDuration, 0.1f); + PlayCrossfade("Gesture, Override", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", chargeDuration, 0.1f); + chargeAnimPlayed = true; + } + } + else if (charge > baseChargeDuration) + { + outer.SetNextState(GetNextStateAuthority()); + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + } + + public override void Update() + { + if (!stateAborted) + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + } + + protected virtual EntityState GetNextStateAuthority() + { + return new FissureSlam(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeartSpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeartSpawnState.cs new file mode 100644 index 0000000..d9f5f6f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeartSpawnState.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class HeartSpawnState : BaseState +{ + [SerializeField] + private float baseAnimDuration = 2f; + + [SerializeField] + private float baseSpawnDuration = 4f; + + [SerializeField] + private GameObject spawnEffect; + + [SerializeField] + private float vfxSize = 6f; + + private bool playedSFX; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound("Play_boss_falseson_spawn", base.gameObject); + Util.PlaySound("Play_boss_falseson_VO_anger", base.gameObject); + PlayAnimation("Body", "Phase1Spawn", "StepBrothersPrep.playbackRate", baseAnimDuration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > 1f && !playedSFX) + { + Util.PlaySound("Play_boss_falseson_VO_anger", base.gameObject); + playedSFX = true; + } + if (base.fixedAge > baseSpawnDuration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeroRelicSwing.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeroRelicSwing.cs new file mode 100644 index 0000000..0c7b61e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeroRelicSwing.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class HeroRelicSwing : BasicMeleeAttack +{ + private float swingTimer; + + protected override void PlayAnimation() + { + string animationStateName = "SwingClubRight"; + float num = Mathf.Max(duration, 0.2f); + PlayCrossfade("Gesture, Additive", animationStateName, "SwingClub.playbackRate", num, 0.1f); + PlayCrossfade("Gesture, Override", animationStateName, "SwingClub.playbackRate", num, 0.1f); + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectMuzzleString = "SwingRight"; + base.BeginMeleeAttackEffect(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + swingTimer += Time.deltaTime; + if (swingTimer > baseDuration) + { + outer.SetNextState(GetNextStateAuthority()); + } + } + + protected virtual EntityState GetNextStateAuthority() + { + return new HeroRelicSwingLeft(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeroRelicSwingLeft.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeroRelicSwingLeft.cs new file mode 100644 index 0000000..a098766 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/HeroRelicSwingLeft.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class HeroRelicSwingLeft : BasicMeleeAttack +{ + private float swingTimer; + + protected override void PlayAnimation() + { + string animationStateName = "SwingClubLeft"; + float num = Mathf.Max(duration, 0.2f); + PlayCrossfade("Gesture, Additive", animationStateName, "SwingClub.playbackRate", num, 0.1f); + PlayCrossfade("Gesture, Override", animationStateName, "SwingClub.playbackRate", num, 0.1f); + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectMuzzleString = "SwingLeft"; + base.BeginMeleeAttackEffect(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + swingTimer += Time.deltaTime; + if (swingTimer > baseDuration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/Lightning1SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/Lightning1SpawnState.cs new file mode 100644 index 0000000..c2aa35a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/Lightning1SpawnState.cs @@ -0,0 +1,42 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class Lightning1SpawnState : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject spawnEffect; + + public static float vfxSize = 6f; + + private bool playedSFX; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound("Play_boss_falseson_spawn", base.gameObject); + PlayAnimation("Body", "Phase2Spawn", "StepBrothersPrep.playbackRate", baseDuration); + PlayAnimation("FullBody, Override", "BufferEmpty"); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("FalseSonBoss/FalseSonBossLightningNovaSpawn"), new EffectData + { + origin = base.transform.position, + scale = vfxSize + }, transmit: true); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > 1f && !playedSFX) + { + Util.PlaySound("Play_boss_falseson_VO_anger", base.gameObject); + playedSFX = true; + } + if (base.fixedAge > baseDuration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/Lightning2SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/Lightning2SpawnState.cs new file mode 100644 index 0000000..c60fa26 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/Lightning2SpawnState.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class Lightning2SpawnState : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject spawnEffect; + + public static float vfxSize = 6f; + + private bool playedSFX; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound("Play_boss_falseson_spawn", base.gameObject); + Util.PlaySound("Play_boss_falseson_VO_anger", base.gameObject); + PlayAnimation("Body", "Phase3Spawn", "StepBrothersPrep.playbackRate", baseDuration); + PlayAnimation("FullBody, Override", "BufferEmpty"); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("FalseSonBoss/FalseSonBossLightningNovaSpawn"), new EffectData + { + origin = base.transform.position, + scale = vfxSize + }, transmit: true); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > 1f && !playedSFX) + { + Util.PlaySound("Play_boss_falseson_VO_anger", base.gameObject); + playedSFX = true; + } + if (base.fixedAge > baseDuration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/List.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/List.cs new file mode 100644 index 0000000..9452a6d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/List.cs @@ -0,0 +1,5 @@ +namespace EntityStates.FalseSonBoss; + +internal class List +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeCharge.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeCharge.cs new file mode 100644 index 0000000..e72bea0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeCharge.cs @@ -0,0 +1,177 @@ +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class LunarGazeCharge : BaseState +{ + public static float baseDuration = 3f; + + public static float laserMaxWidth = 0.2f; + + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject laserPrefab; + + public static string chargeAttackSoundString; + + public static float lockOnAngle; + + private HurtBox lockedOnHurtBox; + + public float duration; + + private GameObject chargeEffect; + + private GameObject laserEffect; + + private LineRenderer laserLineComponent; + + private Vector3 visualEndPosition; + + private float flashTimer; + + private bool laserOn; + + private BullseyeSearch enemyFinder; + + private const float originalSoundDuration = 2.1f; + + protected EntityState fireState; + + public override void OnEnter() + { + base.OnEnter(); + fireState = new LunarGazeFire(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", "LaserBlastStart", "LaserBlast.playbackRate", duration); + PlayAnimation("Gesture, Override", "LaserBlastStart", "LaserBlast.playbackRate", duration); + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(chargeAttackSoundString, base.gameObject, 2.1f / duration); + Ray aimRay = GetAimRay(); + enemyFinder = new BullseyeSearch(); + if ((bool)base.characterBody) + { + enemyFinder.viewer = base.characterBody; + } + enemyFinder.maxDistanceFilter = 2000f; + enemyFinder.maxAngleFilter = lockOnAngle; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.filterByLoS = false; + enemyFinder.sortMode = BullseyeSearch.SortMode.Angle; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleLaser"); + if ((bool)transform) + { + if ((bool)effectPrefab) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)laserPrefab) + { + laserEffect = Object.Instantiate(laserPrefab, transform.position, transform.rotation); + laserEffect.transform.parent = transform; + laserLineComponent = laserEffect.GetComponent(); + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + flashTimer = 0f; + laserOn = true; + } + + public override void OnExit() + { + PlayAnimation("FullBody, Override", "Empty"); + base.OnExit(); + if ((bool)chargeEffect) + { + EntityState.Destroy(chargeEffect); + } + if ((bool)laserEffect) + { + EntityState.Destroy(laserEffect); + } + } + + public override void Update() + { + base.Update(); + if (!laserEffect || !laserLineComponent) + { + return; + } + float num = 1000f; + Ray aimRay = GetAimRay(); + enemyFinder.RefreshCandidates(); + lockedOnHurtBox = enemyFinder.GetResults().FirstOrDefault(); + if ((bool)lockedOnHurtBox) + { + aimRay.direction = lockedOnHurtBox.transform.position - aimRay.origin; + } + Vector3 position = laserEffect.transform.parent.position; + Vector3 point = aimRay.GetPoint(num); + if (Physics.Raycast(aimRay, out var hitInfo, num, (int)LayerIndex.world.mask | (int)LayerIndex.CommonMasks.characterBodiesOrDefault)) + { + point = hitInfo.point; + } + laserLineComponent.SetPosition(0, position); + laserLineComponent.SetPosition(1, point); + float num2; + if (duration - base.age > 0.5f) + { + num2 = base.age / duration; + } + else + { + flashTimer -= Time.deltaTime; + if (flashTimer <= 0f) + { + laserOn = !laserOn; + flashTimer = 1f / 30f; + } + num2 = (laserOn ? 1f : 0f); + } + num2 *= laserMaxWidth; + laserLineComponent.startWidth = num2; + laserLineComponent.endWidth = num2; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + EntityState nextState = fireState; + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeChargePlus.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeChargePlus.cs new file mode 100644 index 0000000..92d4b58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeChargePlus.cs @@ -0,0 +1,10 @@ +namespace EntityStates.FalseSonBoss; + +public class LunarGazeChargePlus : LunarGazeCharge +{ + public override void OnEnter() + { + base.OnEnter(); + fireState = new LunarGazeFirePlus(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeFire.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeFire.cs new file mode 100644 index 0000000..595cf4c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeFire.cs @@ -0,0 +1,250 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class LunarGazeFire : BaseState +{ + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject laserPrefab; + + public static string playAttackSoundString; + + public static string playLoopSoundString; + + public static string stopLoopSoundString; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float fireFrequency; + + public static float maxDistance; + + public static float minimumDuration; + + public static float maximumDuration; + + public static float lockOnAngle; + + public static float procCoefficientPerTick; + + public static DamageType lunarGazeDamageType; + + public static bool isLunarGazePlusPlus; + + private HurtBox lockedOnHurtBox; + + private float fireStopwatch; + + private float stopwatch; + + private Ray aimRay; + + private Transform modelTransform; + + private GameObject laserEffect; + + private ChildLocator laserChildLocator; + + private Transform laserEffectEnd; + + protected Transform muzzleTransform; + + private BullseyeSearch enemyFinder; + + private bool foundAnyTarget; + + public override void OnEnter() + { + base.OnEnter(); + base.characterBody.SetAimTimer(maximumDuration); + Util.PlaySound(playAttackSoundString, base.gameObject); + Util.PlaySound(playLoopSoundString, base.gameObject); + PlayCrossfade("Gesture, Additive", "LaserBlastLoop", 0.25f); + PlayCrossfade("Gesture, Override", "LaserBlastLoop", 0.25f); + enemyFinder = new BullseyeSearch(); + enemyFinder.viewer = base.characterBody; + enemyFinder.maxDistanceFilter = maxDistance; + enemyFinder.maxAngleFilter = lockOnAngle; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.filterByLoS = false; + enemyFinder.sortMode = BullseyeSearch.SortMode.Angle; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + aimRay = GetAimRay(); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild("MuzzleLaser"); + if ((bool)muzzleTransform && (bool)laserPrefab) + { + laserEffect = Object.Instantiate(laserPrefab, muzzleTransform.position, muzzleTransform.rotation); + laserEffect.transform.parent = muzzleTransform; + laserChildLocator = laserEffect.GetComponent(); + laserEffectEnd = laserChildLocator.FindChild("LaserEnd"); + } + } + } + UpdateLockOn(); + } + + public override void OnExit() + { + PlayCrossfade("Gesture, Additive", "Empty", 0.25f); + PlayCrossfade("Gesture, Override", "Empty", 0.25f); + if ((bool)laserEffect) + { + EntityState.Destroy(laserEffect); + } + base.characterBody.SetAimTimer(2f); + Util.PlaySound(stopLoopSoundString, base.gameObject); + base.OnExit(); + } + + private void UpdateLockOn() + { + if (base.isAuthority) + { + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.RefreshCandidates(); + HurtBox hurtBox = enemyFinder.GetResults().FirstOrDefault(); + if (!(lockedOnHurtBox != null) || !(hurtBox == null) || !enemyFinder.CheckVisible(lockedOnHurtBox.healthComponent.gameObject)) + { + lockedOnHurtBox = hurtBox; + foundAnyTarget = hurtBox; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireStopwatch += GetDeltaTime(); + stopwatch += GetDeltaTime(); + aimRay = GetAimRay(); + Vector3 vector = aimRay.origin; + if ((bool)muzzleTransform) + { + vector = muzzleTransform.position; + } + RaycastHit hitInfo; + Vector3 vector2 = (lockedOnHurtBox ? lockedOnHurtBox.transform.position : ((!Util.CharacterRaycast(base.gameObject, aimRay, out hitInfo, maxDistance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) ? aimRay.GetPoint(maxDistance) : hitInfo.point)); + Ray ray = new Ray(vector, vector2 - vector); + bool flag = false; + if ((bool)laserEffect && (bool)laserChildLocator) + { + if (Util.CharacterRaycast(base.gameObject, ray, out var hitInfo2, (vector2 - vector).magnitude, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + vector2 = hitInfo2.point; + if (Util.CharacterRaycast(base.gameObject, new Ray(vector2 - ray.direction * 0.1f, -ray.direction), out var _, hitInfo2.distance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + vector2 = ray.GetPoint(0.1f); + flag = true; + } + } + laserEffect.transform.rotation = Util.QuaternionSafeLookRotation(vector2 - vector); + laserEffectEnd.transform.position = vector2; + } + if (fireStopwatch > 1f / fireFrequency) + { + string targetMuzzle = "MuzzleLaser"; + if (!flag) + { + FireBullet(modelTransform, ray, targetMuzzle, (vector2 - ray.origin).magnitude + 0.1f); + } + UpdateLockOn(); + fireStopwatch -= 1f / fireFrequency; + } + if (base.isAuthority && (((!base.inputBank || !base.inputBank.skill4.down) && stopwatch > minimumDuration) || stopwatch > maximumDuration)) + { + Util.PlaySound("Play_boss_falseson_skill3_lunarGaze_end", base.gameObject); + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + private void FireBullet(Transform modelTransform, Ray aimRay, string targetMuzzle, float maxDistance) + { + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (!base.isAuthority) + { + return; + } + if (isLunarGazePlusPlus) + { + if (Util.CheckRoll(10f)) + { + lunarGazeDamageType = DamageType.LunarRuin; + } + else + { + lunarGazeDamageType = DamageType.Generic; + } + } + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat / fireFrequency; + bulletAttack.force = force; + bulletAttack.damageType = lunarGazeDamageType; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.procCoefficient = procCoefficientPerTick; + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0f; + bulletAttack.maxDistance = maxDistance; + bulletAttack.Fire(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(HurtBoxReference.FromHurtBox(lockedOnHurtBox)); + writer.Write(stopwatch); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + HurtBoxReference hurtBoxReference = reader.ReadHurtBoxReference(); + stopwatch = reader.ReadSingle(); + lockedOnHurtBox = hurtBoxReference.ResolveGameObject()?.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeFirePlus.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeFirePlus.cs new file mode 100644 index 0000000..079450f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarGazeFirePlus.cs @@ -0,0 +1,24 @@ +using RoR2; + +namespace EntityStates.FalseSonBoss; + +public class LunarGazeFirePlus : LunarGazeFire +{ + public static float plusDamageCoefficient; + + public override void OnEnter() + { + LunarGazeFire.playAttackSoundString = "Play_boss_falseson_skill3plus_lunarGaze_start"; + LunarGazeFire.playLoopSoundString = "Play_boss_falseson_skill3plus_lunarGaze_active_loop"; + LunarGazeFire.stopLoopSoundString = "Stop_boss_falseson_skill3plus_lunarGaze_active_loop"; + LunarGazeFire.isLunarGazePlusPlus = true; + LunarGazeFire.damageCoefficient += plusDamageCoefficient; + base.OnEnter(); + } + + public override void OnExit() + { + Util.PlaySound("Play_boss_falseson_skill3plus_lunarGaze_end", base.gameObject); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarRain.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarRain.cs new file mode 100644 index 0000000..5fff8e8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/LunarRain.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using RoR2; +using RoR2.Navigation; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class LunarRain : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public float warningDuration; + + [SerializeField] + public float delayBetweenDrops = 0.2f; + + [SerializeField] + public float lunarRadius; + + [SerializeField] + public int totalLunarDrops = 7; + + [SerializeField] + public float percentVarianceRotation = 0.25f; + + [SerializeField] + public float percentVarianceInRadius = 0.2f; + + public static GameObject warningFXPrefab; + + public static GameObject rainCrashEffectPrefab; + + public static GameObject lunarRainPrefab; + + public static GameObject blastImpactEffectPrefab; + + [SerializeField] + public GameObject blastEffectPrefab; + + [SerializeField] + public float blastRadius = 2f; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static Vector3 blastBonusForce; + + private NodeGraph nodeGraph; + + private List nodesToTeleportTo; + + private List fissureLocs; + + private Vector3 fissureLocation; + + private bool lunarRainStarted; + + private float lunarRainStartTime; + + private int totalWarned; + + private int totalFired; + + private int totalLunarDropsToFire; + + private float nextDropTime; + + public override void OnEnter() + { + base.OnEnter(); + new System.Random(); + nodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + fissureLocs = new List(); + totalLunarDrops = ((totalLunarDrops > 0) ? totalLunarDrops : 7); + float num = ((lunarRadius > 0f) ? lunarRadius : 30f); + Transform transform = base.characterBody.transform; + Vector3 position = transform.position; + Vector3 angleOffset2 = Quaternion.AngleAxis(-90f, Vector3.up) * transform.forward; + angleOffset2.y = 0f; + NodeGraph.NodeIndex nodeIndex = nodeGraph.FindClosestNode(position, HullClassification.Human); + for (int j = 0; j < totalLunarDrops; j++) + { + Vector3 position2 = GeneratePositionAroundCircle(j, totalLunarDrops, position, num * UnityEngine.Random.Range(0.7f, 1.3f), angleOffset2); + NodeGraph.NodeIndex nodeIndex2 = SceneInfo.instance.groundNodes.FindClosestNode(position2, HullClassification.Human); + if (!fissureLocs.Contains(nodeIndex2) && nodeIndex2 != nodeIndex) + { + fissureLocs.Add(nodeIndex2); + } + else + { + num *= 1.5f; + } + } + Util.ShuffleList(fissureLocs); + totalFired = 0; + nextDropTime = base.fixedAge + delayBetweenDrops; + totalLunarDropsToFire = Mathf.Min(totalLunarDrops, fissureLocs.Count); + PlayAnimation("FullBody, Override", "LunarRain", "LunarRain.playbackRate", duration); + Vector3 GeneratePositionAroundCircle(int i, int total, Vector3 center, float radius, Vector3 angleOffset) + { + float num2 = MathF.PI * 2f / (float)total; + float f = num2 * (float)i + num2 * UnityEngine.Random.Range(1f - percentVarianceRotation, 1f + percentVarianceRotation); + float x = Mathf.Cos(f); + float z = Mathf.Sin(f); + Vector3 vector = new Vector3(x, 0f, z); + radius *= UnityEngine.Random.Range(1f - percentVarianceInRadius, 1f + percentVarianceInRadius); + return vector * radius + center; + } + } + + private void SpawnRainWarning(NodeGraph.NodeIndex node) + { + nodeGraph.GetNodePosition(node, out fissureLocation); + EffectManager.SpawnEffect(warningFXPrefab, new EffectData + { + origin = fissureLocation + }, transmit: true); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (totalWarned < totalLunarDropsToFire) + { + SpawnRainWarning(fissureLocs[totalWarned++]); + if (totalWarned >= totalLunarDropsToFire) + { + lunarRainStartTime = base.fixedAge + warningDuration + duration * 0.7f; + } + return; + } + if (!lunarRainStarted && base.fixedAge > lunarRainStartTime) + { + lunarRainStarted = true; + DetonateAuthority(); + } + if (!lunarRainStarted || base.fixedAge < nextDropTime) + { + return; + } + if (totalFired >= totalLunarDropsToFire) + { + outer.SetNextStateToMain(); + return; + } + FireRain(fissureLocs[totalFired++]); + if (totalFired < totalLunarDropsToFire) + { + FireRain(fissureLocs[totalFired++]); + } + } + + private void FireRain(NodeGraph.NodeIndex node) + { + if (NetworkServer.active) + { + nodeGraph.GetNodePosition(node, out fissureLocation); + nextDropTime = base.fixedAge + delayBetweenDrops; + EffectManager.SpawnEffect(rainCrashEffectPrefab, new EffectData + { + origin = fissureLocation + }, transmit: true); + NetworkServer.Spawn(UnityEngine.Object.Instantiate(lunarRainPrefab, fissureLocation, Quaternion.identity)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 position = FindModelChild("Root").transform.position; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = position, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = base.gameObject.transform.position, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/OverloadSpike.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/OverloadSpike.cs new file mode 100644 index 0000000..9cde175 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/OverloadSpike.cs @@ -0,0 +1,93 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class OverloadSpike : BaseState +{ + [SerializeField] + public float duration; + + public static GameObject rainCrashEffectPrefab; + + public static GameObject lunarRainPrefab; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static Vector3 blastBonusForce; + + private bool firedSpike; + + public override void OnEnter() + { + base.OnEnter(); + if (!base.characterBody.GetComponent().firedLunarSpike) + { + PlayAnimation("FullBody, Override", "OverloadErruption", "OverloadErruption.playbackRate", duration); + } + else + { + outer.SetNextStateToMain(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration - duration * 0.3f && !firedSpike && !base.characterBody.GetComponent().firedLunarSpike) + { + DetonateAuthority(); + base.characterBody.GetComponent().SpawnLunarSpike(); + firedSpike = true; + } + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + outer.SetNextStateToMain(); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + protected BlastAttack.Result DetonateAuthority() + { + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = base.gameObject.transform.position, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = base.gameObject.transform.position, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/PrimeDevastator.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/PrimeDevastator.cs new file mode 100644 index 0000000..ea381ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/PrimeDevastator.cs @@ -0,0 +1,192 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class PrimeDevastator : BaseState +{ + [SerializeField] + private float duration = 4f; + + [SerializeField] + private float damageCoefficient = 2f; + + public static float slamEffectDelay; + + public static float playerLightningDelay; + + public static GameObject projectilePrefab; + + private Transform modelTransform; + + protected Transform muzzleTransform; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static GameObject disablingLightningPrefab; + + public static GameObject lightningEffectPrefab; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static Vector3 blastBonusForce; + + private Ray projectileRay; + + public static float arcAngle = 7f; + + public static float spreadBloomValue = 0.3f; + + public static GameObject chargeEffectPrefab; + + private bool chargeEffectSpawned; + + private bool slamEffectSpawned; + + private bool playerLightningSpawned; + + private bool orbsSpawned; + + private float orbSpawnTimer; + + private int orbNumber; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("FullBody, Override", "PrimeDevastator", "PrimeDevastator.playbackRate", duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!chargeEffectSpawned && base.fixedAge > duration * 0.3f) + { + chargeEffectSpawned = true; + EffectManager.SpawnEffect(chargeEffectPrefab, new EffectData + { + origin = base.gameObject.transform.position, + scale = 10f + }, transmit: true); + } + if (!slamEffectSpawned && base.fixedAge > slamEffectDelay) + { + slamEffectSpawned = true; + DetonateAuthority(); + } + if (!playerLightningSpawned && base.isAuthority && base.fixedAge > playerLightningDelay) + { + playerLightningSpawned = true; + if ((bool)disablingLightningPrefab) + { + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + if (!(instance == null)) + { + CharacterBody body = instance.master.GetBody(); + if (!(body == null)) + { + body.AddTimedBuff(DLC2Content.Buffs.DisableAllSkills, 420f); + EffectManager.SpawnEffect(lightningEffectPrefab, new EffectData + { + origin = body.corePosition, + scale = blastRadius + }, transmit: true); + } + } + } + } + } + if (!orbsSpawned && base.isAuthority && base.fixedAge > playerLightningDelay) + { + orbSpawnTimer += Time.deltaTime; + if (orbSpawnTimer > 0.5f) + { + FireDevastator("MuzzleOrb1"); + orbNumber++; + orbSpawnTimer = 0f; + } + if (orbNumber >= 4) + { + orbsSpawned = true; + } + } + if (base.fixedAge >= duration + 1f && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireDevastator(string targetMuzzle) + { + projectileRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + projectileRay.origin = transform.position; + } + } + } + if (base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = base.gameObject.transform.position + new Vector3(7f, 0f, 0f); + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = 0f; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected BlastAttack.Result DetonateAuthority() + { + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = base.gameObject.transform.position, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = base.gameObject.transform.position, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SkyJumpDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SkyJumpDeathState.cs new file mode 100644 index 0000000..9ccc103 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SkyJumpDeathState.cs @@ -0,0 +1,197 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonBoss; + +public class SkyJumpDeathState : GenericCharacterDeath +{ + [SerializeField] + public float duration = 4.5f; + + public GameObject deathEffectPrefab; + + public float vfxSize = 8f; + + private float beginUpwardMovementTime = 0.96086955f; + + private bool startedFlying; + + private Vector3 cachedDeathPosition; + + private bool _shouldAutoDestroy; + + [SerializeField] + public GameObject falseSonJumpAwayVFX; + + [SerializeField] + public ItemTier rewardDisplayTier; + + [Tooltip("The prefab to use for the reward pickup.")] + [SerializeField] + public GameObject rewardPickupPrefab; + + [SerializeField] + public Vector3 rewardOffset; + + [SerializeField] + public string falseSonSurvivorAchievement; + + private PickupIndex halcyonSeed; + + [SerializeField] + public int rewardOptionCount = 1; + + [SerializeField] + public PickupDropTable dtColossusBuffDropTable; + + public bool rewardGiven; + + private bool playedSFX; + + protected override bool shouldAutoDestroy => _shouldAutoDestroy; + + public static event Action falseSonDeathEvent; + + public static event Action falseSonUnlockEvent; + + public override void OnEnter() + { + base.OnEnter(); + SkyJumpDeathState.falseSonDeathEvent?.Invoke(); + beginUpwardMovementTime *= duration; + cachedDeathPosition = base.gameObject.transform.position; + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("FalseSonBoss/FalseSonBossLightningStreakDeath"), new EffectData + { + origin = base.characterBody.corePosition, + scale = vfxSize + }, transmit: true); + halcyonSeed = PickupCatalog.FindPickupIndex("TitanGoldDuringTP"); + GiveColossusItem(); + } + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayAnimation("FullBody, Override", "Phase3Death", "StepBrothersPrep.playbackRate", duration); + Util.PlaySound("Play_boss_falseson_VO_defeat", base.gameObject); + MeridianEventTriggerInteraction.instance.musicPhaseThree.SetActive(value: false); + MeridianEventTriggerInteraction.instance.musicPhaseBossDead.SetActive(value: true); + } + + public override void FixedUpdate() + { + if (base.fixedAge >= 0.35f && !playedSFX) + { + Util.PlaySound("Play_boss_falseson_phaseTransition_kneel", base.characterBody.gameObject); + Util.PlaySound("Play_boss_falseson_VO_groan", base.characterBody.gameObject); + playedSFX = true; + } + if (base.fixedAge > beginUpwardMovementTime) + { + if (!startedFlying) + { + if (NetworkServer.active) + { + LightningStormController.SetStormActive(b: false); + } + startedFlying = true; + EffectManager.SpawnEffect(falseSonJumpAwayVFX, new EffectData + { + origin = cachedDeathPosition + }, transmit: false); + } + base.characterMotor.rootMotion += Vector3.up * moveSpeedStat; + } + if (!_shouldAutoDestroy && NetworkServer.active && base.fixedAge >= duration + 0.5f) + { + _shouldAutoDestroy = true; + } + base.FixedUpdate(); + } + + public override void OnExit() + { + DestroyBodyAsapServer(); + DestroyModel(); + base.OnExit(); + MeridianEventTriggerInteraction.FSBFPhaseBaseState.readyToSpawnNextBossBody = true; + DestroyBodyServer(); + } + + private void DestroyBodyServer() + { + if (NetworkServer.active) + { + OnPreDestroyBodyServer(); + EntityState.Destroy(base.gameObject); + } + } + + private void GiveColossusItem() + { + if (!NetworkServer.active) + { + return; + } + int participatingPlayerCount = Run.instance.participatingPlayerCount; + if (dtColossusBuffDropTable == null || participatingPlayerCount == 0) + { + return; + } + if (FalseSonUnlockStateMet()) + { + SkyJumpDeathState.falseSonUnlockEvent?.Invoke(); + dtColossusBuffDropTable = LegacyResourcesAPI.Load("DropTables/dtAurelioniteHeartPickupDropTable"); + } + Xoroshiro128Plus rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong); + if (participatingPlayerCount > 0 && (bool)base.gameObject && (bool)dtColossusBuffDropTable && !rewardGiven) + { + rewardGiven = true; + int num = participatingPlayerCount; + float angle = 360f / (float)num; + Vector3 vector = Quaternion.AngleAxis(UnityEngine.Random.Range(0, 360), Vector3.up) * (Vector3.up * 40f + Vector3.forward * 5f); + Quaternion quaternion = Quaternion.AngleAxis(angle, Vector3.up); + Vector3 position = cachedDeathPosition + rewardOffset; + int num2 = 0; + while (num2 < num) + { + GenericPickupController.CreatePickupInfo pickupInfo = default(GenericPickupController.CreatePickupInfo); + pickupInfo.pickupIndex = PickupCatalog.FindPickupIndex(rewardDisplayTier); + pickupInfo.pickerOptions = PickupPickerController.GenerateOptionsFromDropTable(rewardOptionCount, dtColossusBuffDropTable, rng); + pickupInfo.rotation = Quaternion.identity; + pickupInfo.prefabOverride = rewardPickupPrefab; + PickupDropletController.CreatePickupDroplet(pickupInfo, position, vector); + num2++; + vector = quaternion * vector; + } + } + } + + private bool FalseSonUnlockStateMet() + { + bool result = false; + if (MeridianEventTriggerInteraction.instance.isGoldTitanSpawned) + { + return true; + } + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + if (!(instance == null) && instance.master.inventory.GetItemCount(RoR2Content.Items.TitanGoldDuringTP) > 0) + { + result = true; + GameObject effectPrefab = LegacyResourcesAPI.Load("Prefabs/Effects/DelusionItemDissolveVFX"); + EffectData effectData = new EffectData + { + origin = instance.master.GetBody().transform.position, + genericFloat = 1.5f, + genericUInt = (uint)(halcyonSeed.itemIndex + 1) + }; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + instance.master.inventory.RemoveItem(halcyonSeed.itemIndex); + } + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SwatAwayPlayersSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SwatAwayPlayersSlam.cs new file mode 100644 index 0000000..63d24f3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SwatAwayPlayersSlam.cs @@ -0,0 +1,144 @@ +using RoR2; +using RoR2.Audio; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class SwatAwayPlayersSlam : BaseCharacterMain +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public string hitBoxGroupName; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float pushAwayForce; + + [SerializeField] + public Vector3 forceVector; + + [SerializeField] + public NetworkSoundEventDef impactSound; + + public float charge; + + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static string enterSoundString; + + public static Vector3 blastBonusForce; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static GameObject fistEffectPrefab; + + public static GameObject swingEffectPrefab; + + public static GameObject fissureSlamObject; + + private GameObject swingEffectInstance; + + private bool detonateNextFrame; + + private bool slamComplete; + + protected HitBoxGroup hitBoxGroup; + + private OverlapAttack overlapAttack; + + public override void OnEnter() + { + base.OnEnter(); + baseDuration /= attackSpeedStat; + PlayAnimation("FullBody, Override", "ChargeSwing", "ChargeSwing.playbackRate", baseDuration); + Util.PlaySound(enterSoundString, base.gameObject); + swingEffectInstance = Object.Instantiate(swingEffectPrefab, FindModelChild("OverHeadSwingPoint")); + if (base.isAuthority) + { + hitBoxGroup = FindHitBoxGroup(GetHitBoxGroupName()); + if ((bool)hitBoxGroup) + { + overlapAttack = new OverlapAttack + { + attacker = base.gameObject, + damage = damageCoefficient * damageStat, + damageColorIndex = DamageColorIndex.Default, + damageType = DamageType.Generic, + forceVector = forceVector, + hitBoxGroup = hitBoxGroup, + hitEffectPrefab = hitEffectPrefab, + impactSound = (impactSound?.index ?? NetworkSoundEventIndex.Invalid), + inflictor = base.gameObject, + isCrit = RollCrit(), + procChainMask = default(ProcChainMask), + pushAwayForce = pushAwayForce, + procCoefficient = procCoefficient, + teamIndex = GetTeam() + }; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!slamComplete && base.fixedAge >= baseDuration - baseDuration * 0.8f) + { + BeginMeleeAttack(); + slamComplete = true; + } + if (slamComplete) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + protected void BeginMeleeAttack() + { + Vector3 position = FindModelChild("ClubExplosionPoint").transform.position; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = position, + scale = blastRadius + }, transmit: true); + if (base.isAuthority && overlapAttack != null) + { + overlapAttack.Fire(); + } + } + + public virtual string GetHitBoxGroupName() + { + return hitBoxGroupName; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SwatAwayPlayersWindup.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SwatAwayPlayersWindup.cs new file mode 100644 index 0000000..3fb1fe0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/SwatAwayPlayersWindup.cs @@ -0,0 +1,125 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class SwatAwayPlayersWindup : BaseSkillState +{ + [SerializeField] + public float baseChargeDuration = 1f; + + [SerializeField] + public float chargeThreshold = 3f; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private int gauntlet; + + private uint soundID; + + private Transform chargeVfxInstanceTransform; + + private bool chargeAnimPlayed; + + private bool stateAborted; + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = 0.5f; + Util.PlaySound(enterSFXString, base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + public override void OnExit() + { + if (!stateAborted) + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + PlayAnimation("Gesture, Additive", "Empty"); + PlayAnimation("Gesture, Override", "Empty"); + chargeVfxInstanceTransform = null; + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + } + + public override void FixedUpdate() + { + if (stateAborted) + { + return; + } + base.FixedUpdate(); + charge += Time.deltaTime; + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge <= 3f && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform) + { + chargeVfxInstanceTransform = Object.Instantiate(chargeVfxPrefab, transform).transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeForChargedAttack) * chargeDuration; + } + } + if (!chargeAnimPlayed) + { + PlayCrossfade("Gesture, Additive", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", chargeDuration, 0.1f); + PlayCrossfade("Gesture, Override", "ChargeSwingIntro", "ChargeSwingIntro.playbackRate", chargeDuration, 0.1f); + chargeAnimPlayed = true; + } + } + else if (charge > baseChargeDuration) + { + outer.SetNextState(GetNextStateAuthority()); + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + } + + public override void Update() + { + if (!stateAborted) + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + } + + protected virtual EntityState GetNextStateAuthority() + { + return new SwatAwayPlayersSlam(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/TaintedOffering.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/TaintedOffering.cs new file mode 100644 index 0000000..f0e4c93 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonBoss/TaintedOffering.cs @@ -0,0 +1,120 @@ +using RoR2; +using RoR2.CharacterAI; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.FalseSonBoss; + +public class TaintedOffering : GenericProjectileBaseState +{ + [SerializeField] + public float projectileYawBonus; + + [SerializeField] + public float additionalShots = 8f; + + private BaseAI ai; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody) + { + if (base.characterBody.master.TryGetComponent(out var component)) + { + ai = component; + } + base.characterBody.SetAimTimer(1f); + } + } + + public override void FixedUpdate() + { + stopwatch += GetDeltaTime(); + if (stopwatch >= delayBeforeFiringProjectile && !firedProjectile) + { + firedProjectile = true; + for (int num = 9; num > 0; num--) + { + switch (num) + { + case 9: + projectileYawBonus = 0f; + projectilePitchBonus = 0f; + break; + case 8: + projectileYawBonus = -4f; + projectilePitchBonus = -4f; + break; + case 7: + projectileYawBonus = 4f; + projectilePitchBonus = 4f; + break; + case 6: + projectileYawBonus = 4f; + projectilePitchBonus = -4f; + break; + case 5: + projectileYawBonus = -4f; + projectilePitchBonus = 4f; + break; + case 4: + projectileYawBonus = 0f; + projectilePitchBonus = 8f; + break; + case 3: + projectileYawBonus = 0f; + projectilePitchBonus = -8f; + break; + case 2: + projectileYawBonus = 8f; + projectilePitchBonus = 0f; + break; + case 1: + projectileYawBonus = -8f; + projectilePitchBonus = 0f; + break; + } + FireProjectile(); + } + DoFireEffects(); + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + protected override void PlayAnimation(float duration) + { + base.PlayAnimation(duration); + PlayAnimation("Gesture, Additive", "FireLunarSpike", "LunarSpike.playbackRate", duration); + PlayAnimation("Gesture, Override", "HoldGauntletsUp", "LunarSpike.playbackRate", duration); + } + + protected override Ray ModifyProjectileAimRay(Ray aimRay) + { + aimRay.origin = base.modelLocator.modelTransform.GetComponent().FindChild("MuzzleRight").position; + if (ai != null && ai.currentEnemy != null && ai.currentEnemy.GetBullseyePosition(out var position)) + { + aimRay.direction = position - aimRay.origin; + } + return aimRay; + } + + protected override void FireProjectile() + { + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + aimRay = ModifyProjectileAimRay(aimRay); + aimRay.direction = Util.ApplySpread(aimRay.direction, minSpread, maxSpread, 1f, 1f, projectileYawBonus, projectilePitchBonus); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FalseSonMeteorPod/Descent.cs b/ilspy_dump/ror2_csproj/EntityStates.FalseSonMeteorPod/Descent.cs new file mode 100644 index 0000000..02fdb24 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FalseSonMeteorPod/Descent.cs @@ -0,0 +1,31 @@ +using EntityStates.SurvivorPod; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FalseSonMeteorPod; + +public class Descent : EntityStates.SurvivorPod.Descent +{ + public static GameObject effectPrefab; + + protected override void TransitionIntoNextState() + { + base.TransitionIntoNextState(); + } + + public override void OnExit() + { + VehicleSeat component = GetComponent(); + if ((bool)component) + { + component.EjectPassenger(); + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, "Base", transmit: true); + } + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Fauna/BirdsharkDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Fauna/BirdsharkDeathState.cs new file mode 100644 index 0000000..e1b5ddb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Fauna/BirdsharkDeathState.cs @@ -0,0 +1,41 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Fauna; + +public class BirdsharkDeathState : BaseState +{ + [SerializeField] + public GameObject initialExplosion; + + [SerializeField] + public string deathSoundString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(deathSoundString, base.gameObject); + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if ((bool)initialExplosion && NetworkServer.active) + { + EffectManager.SimpleImpactEffect(initialExplosion, base.transform.position, Vector3.up, transmit: true); + } + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Fauna/HabitatFruitDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Fauna/HabitatFruitDeathState.cs new file mode 100644 index 0000000..6c33f50 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Fauna/HabitatFruitDeathState.cs @@ -0,0 +1,50 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Fauna; + +public class HabitatFruitDeathState : BaseState +{ + [SerializeField] + public static GameObject initialExplosion; + + [SerializeField] + public static string deathSoundString; + + public static int healPackCount; + + public static float healPackMaxVelocity; + + public static float fractionalHealing; + + public static float scale; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(deathSoundString, base.gameObject); + if ((bool)initialExplosion && NetworkServer.active) + { + EffectManager.SimpleImpactEffect(initialExplosion, base.transform.position, Vector3.up, transmit: true); + } + if (NetworkServer.active) + { + for (int i = 0; i < healPackCount; i++) + { + GameObject obj = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/HealPack"), base.transform.position, Random.rotation); + obj.GetComponent().teamIndex = TeamIndex.Player; + obj.GetComponentInChildren().fractionalHealing = fractionalHealing; + obj.transform.localScale = new Vector3(scale, scale, scale); + obj.GetComponent().AddForce(Random.insideUnitSphere * healPackMaxVelocity, ForceMode.VelocityChange); + NetworkServer.Spawn(obj); + } + } + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Fauna/VultureEggDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Fauna/VultureEggDeathState.cs new file mode 100644 index 0000000..67eaa3e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Fauna/VultureEggDeathState.cs @@ -0,0 +1,33 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Fauna; + +public class VultureEggDeathState : BirdsharkDeathState +{ + public static int healPackCount; + + public static float healPackMaxVelocity; + + public static float fractionalHealing; + + public static float scale; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + for (int i = 0; i < healPackCount; i++) + { + GameObject obj = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/HealPack"), base.transform.position, Random.rotation); + obj.GetComponent().teamIndex = TeamIndex.Player; + obj.GetComponentInChildren().fractionalHealing = fractionalHealing; + obj.transform.localScale = new Vector3(scale, scale, scale); + obj.GetComponent().AddForce(Random.insideUnitSphere * healPackMaxVelocity, ForceMode.VelocityChange); + NetworkServer.Spawn(obj); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin.Mode/GrantFlight.cs b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin.Mode/GrantFlight.cs new file mode 100644 index 0000000..f6bd636 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin.Mode/GrantFlight.cs @@ -0,0 +1,46 @@ +using RoR2; + +namespace EntityStates.FlyingVermin.Mode; + +public class GrantFlight : BaseState +{ + protected ICharacterGravityParameterProvider characterGravityParameterProvider; + + protected ICharacterFlightParameterProvider characterFlightParameterProvider; + + public override void OnEnter() + { + base.OnEnter(); + characterGravityParameterProvider = base.gameObject.GetComponent(); + characterFlightParameterProvider = base.gameObject.GetComponent(); + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount++; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount++; + characterFlightParameterProvider.flightParameters = flightParameters; + } + } + + public override void OnExit() + { + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount--; + characterFlightParameterProvider.flightParameters = flightParameters; + } + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount--; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin.Weapon/Spit.cs b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin.Weapon/Spit.cs new file mode 100644 index 0000000..fee25cb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin.Weapon/Spit.cs @@ -0,0 +1,52 @@ +using RoR2; +using RoR2.CharacterAI; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.FlyingVermin.Weapon; + +public class Spit : GenericProjectileBaseState +{ + private static int SpitStateHash = Animator.StringToHash("Spit"); + + private static int SpitParamHash = Animator.StringToHash("Spit.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(5f); + } + } + + protected override void PlayAnimation(float duration) + { + base.PlayAnimation(duration); + PlayAnimation("Gesture, Additive", SpitStateHash, SpitParamHash, duration); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + protected override void FireProjectile() + { + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + aimRay = ModifyProjectileAimRay(aimRay); + aimRay.direction = Util.ApplySpread(aimRay.direction, minSpread, maxSpread, 1f, 1f, 0f, projectilePitchBonus); + float damage = damageStat * damageCoefficient; + BaseAI component = outer.commonComponents.characterBody.master.GetComponent(); + if ((object)component != null && component.shouldMissFirstOffScreenShot && component.currentEnemy.characterBody.teamComponent.teamIndex == TeamIndex.Player) + { + component.shouldMissFirstOffScreenShot = false; + aimRay.direction = OffScreenMissHelper.ApplyRandomTrajectoryOffset(aimRay.direction); + damage = 0f; + } + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damage, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin/FallingDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin/FallingDeath.cs new file mode 100644 index 0000000..fca3fdd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin/FallingDeath.cs @@ -0,0 +1,42 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.FlyingVermin; + +public class FallingDeath : GenericCharacterDeath +{ + public static float initialVerticalVelocity; + + public static float deathDelay; + + public static GameObject deathEffectPrefab; + + private bool hasDied; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity.y = initialVerticalVelocity; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > deathDelay && NetworkServer.active && !hasDied) + { + hasDied = true; + EffectManager.SimpleImpactEffect(deathEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: true); + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin/SpawnState.cs new file mode 100644 index 0000000..b878bf6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.FlyingVermin/SpawnState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.FlyingVermin; + +public class SpawnState : GenericCharacterSpawnState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/BaseGameOverControllerState.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/BaseGameOverControllerState.cs new file mode 100644 index 0000000..33d7165 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/BaseGameOverControllerState.cs @@ -0,0 +1,17 @@ +using RoR2; + +namespace EntityStates.GameOver; + +public class BaseGameOverControllerState : BaseState +{ + protected GameOverController gameOverController { get; private set; } + + protected GameEndingDef gameEnding { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + gameOverController = GetComponent(); + gameEnding = gameOverController.runReport.gameEnding; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/FinishEndingContent.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/FinishEndingContent.cs new file mode 100644 index 0000000..4913a9e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/FinishEndingContent.cs @@ -0,0 +1,15 @@ +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class FinishEndingContent : BaseGameOverControllerState +{ + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + outer.SetNextState(base.gameEnding.showCredits ? ((BaseGameOverControllerState)new ShowCredits()) : ((BaseGameOverControllerState)new ShowReport())); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/LingerShort.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/LingerShort.cs new file mode 100644 index 0000000..5863871 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/LingerShort.cs @@ -0,0 +1,17 @@ +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class LingerShort : BaseGameOverControllerState +{ + private static readonly float duration = 3f; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/RebirthEndingFadeToBlack.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RebirthEndingFadeToBlack.cs new file mode 100644 index 0000000..c402aed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RebirthEndingFadeToBlack.cs @@ -0,0 +1,75 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.UI; + +namespace EntityStates.GameOver; + +public class RebirthEndingFadeToBlack : BaseGameOverControllerState +{ + [SerializeField] + public float delay; + + [SerializeField] + public float duration; + + [SerializeField] + public GameObject screenPrefab; + + private Run.TimeStamp startTime; + + private Image image; + + private GameObject screenInstance; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + startTime = Run.TimeStamp.now + delay; + } + screenInstance = Object.Instantiate(screenPrefab, RoR2Application.instance.mainCanvas.transform); + image = screenInstance.GetComponentInChildren(); + image.raycastTarget = false; + UpdateImageAlpha(0f); + } + + public override void OnExit() + { + FadeToBlackManager.ForceFullBlack(); + EntityState.Destroy(screenInstance); + screenInstance = null; + image = null; + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(startTime); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + startTime = reader.ReadTimeStamp(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + UpdateImageAlpha(Mathf.Max(0f, Mathf.Min(1f, startTime.timeSince / duration))); + if (NetworkServer.active && (startTime + duration).hasPassed) + { + outer.SetNextStateToMain(); + } + } + + private void UpdateImageAlpha(float finalAlpha) + { + Color color = image.color; + color.a = finalAlpha; + image.color = color; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/RebirthEndingStart.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RebirthEndingStart.cs new file mode 100644 index 0000000..caf3e67 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RebirthEndingStart.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class RebirthEndingStart : BaseGameOverControllerState +{ + [SerializeField] + public float duration; + + private bool hasSceneExited; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration && hasSceneExited) + { + outer.SetNextState(new RebirthEndingFadeToBlack()); + } + } + + public override void OnEnter() + { + base.OnEnter(); + SceneExitController.onFinishExit += OnFinishSceneExit; + } + + public override void OnExit() + { + SceneExitController.onFinishExit -= OnFinishSceneExit; + base.OnExit(); + } + + private void OnFinishSceneExit(SceneExitController obj) + { + hasSceneExited = true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingPlayCutscene.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingPlayCutscene.cs new file mode 100644 index 0000000..8f7a3a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingPlayCutscene.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class RoR2MainEndingPlayCutscene : BaseGameOverControllerState +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (!OutroCutsceneController.instance || OutroCutsceneController.instance.cutsceneIsFinished)) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)OutroCutsceneController.instance && (bool)OutroCutsceneController.instance.playableDirector) + { + OutroCutsceneController.instance.playableDirector.time = OutroCutsceneController.instance.playableDirector.duration; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingSetSceneAndWaitForPlayers.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingSetSceneAndWaitForPlayers.cs new file mode 100644 index 0000000..e91f939 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingSetSceneAndWaitForPlayers.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class RoR2MainEndingSetSceneAndWaitForPlayers : BaseGameOverControllerState +{ + private SceneDef desiredSceneDef; + + public override void OnEnter() + { + base.OnEnter(); + FadeToBlackManager.ForceFullBlack(); + FadeToBlackManager.fadeCount++; + desiredSceneDef = SceneCatalog.GetSceneDefFromSceneName("outro"); + if (NetworkServer.active) + { + Run.instance.AdvanceStage(desiredSceneDef); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && NetworkUser.AllParticipatingNetworkUsersReady() && SceneCatalog.mostRecentSceneDef == desiredSceneDef) + { + outer.SetNextState(new RoR2MainEndingPlayCutscene()); + } + } + + public override void OnExit() + { + FadeToBlackManager.fadeCount--; + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingStart.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingStart.cs new file mode 100644 index 0000000..056588f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/RoR2MainEndingStart.cs @@ -0,0 +1,27 @@ +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class RoR2MainEndingStart : BaseGameOverControllerState +{ + public static float duration = 6f; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextState(new RoR2MainEndingSetSceneAndWaitForPlayers()); + } + } + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/ShowCredits.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/ShowCredits.cs new file mode 100644 index 0000000..a6c83a0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/ShowCredits.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class ShowCredits : BaseGameOverControllerState +{ + private GameObject creditsControllerInstance; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + creditsControllerInstance = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/CreditsController")); + NetworkServer.Spawn(creditsControllerInstance); + } + } + + public override void OnExit() + { + if (NetworkServer.active && (bool)creditsControllerInstance) + { + EntityState.Destroy(creditsControllerInstance); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && !creditsControllerInstance) + { + outer.SetNextState(new ShowReport()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/ShowReport.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/ShowReport.cs new file mode 100644 index 0000000..0c04fc9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/ShowReport.cs @@ -0,0 +1,20 @@ +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class ShowReport : BaseGameOverControllerState +{ + public override void OnEnter() + { + base.OnEnter(); + if (NetworkClient.active) + { + base.gameOverController.shouldDisplayGameEndReportPanels = true; + } + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingFadeToBlack.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingFadeToBlack.cs new file mode 100644 index 0000000..30b9107 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingFadeToBlack.cs @@ -0,0 +1,75 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.UI; + +namespace EntityStates.GameOver; + +public class VoidEndingFadeToBlack : BaseGameOverControllerState +{ + [SerializeField] + public float delay; + + [SerializeField] + public float duration; + + [SerializeField] + public GameObject screenPrefab; + + private Run.TimeStamp startTime; + + private Image image; + + private GameObject screenInstance; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + startTime = Run.TimeStamp.now + delay; + } + screenInstance = Object.Instantiate(screenPrefab, RoR2Application.instance.mainCanvas.transform); + image = screenInstance.GetComponentInChildren(); + image.raycastTarget = false; + UpdateImageAlpha(0f); + } + + public override void OnExit() + { + FadeToBlackManager.ForceFullBlack(); + EntityState.Destroy(screenInstance); + screenInstance = null; + image = null; + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(startTime); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + startTime = reader.ReadTimeStamp(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + UpdateImageAlpha(Mathf.Max(0f, Mathf.Min(1f, startTime.timeSince / duration))); + if (NetworkServer.active && (startTime + duration).hasPassed) + { + outer.SetNextStateToMain(); + } + } + + private void UpdateImageAlpha(float finalAlpha) + { + Color color = image.color; + color.a = finalAlpha; + image.color = color; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingPlayCutscene.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingPlayCutscene.cs new file mode 100644 index 0000000..04ca8a4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingPlayCutscene.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class VoidEndingPlayCutscene : BaseGameOverControllerState +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (!OutroCutsceneController.instance || OutroCutsceneController.instance.cutsceneIsFinished)) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)OutroCutsceneController.instance && (bool)OutroCutsceneController.instance.playableDirector) + { + OutroCutsceneController.instance.playableDirector.time = OutroCutsceneController.instance.playableDirector.duration; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingSetSceneAndWaitForPlayers.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingSetSceneAndWaitForPlayers.cs new file mode 100644 index 0000000..5bd1aba --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingSetSceneAndWaitForPlayers.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class VoidEndingSetSceneAndWaitForPlayers : BaseGameOverControllerState +{ + [SerializeField] + public SceneDef desiredSceneDef; + + public override void OnEnter() + { + base.OnEnter(); + FadeToBlackManager.ForceFullBlack(); + FadeToBlackManager.fadeCount++; + if (NetworkServer.active) + { + Run.instance.AdvanceStage(desiredSceneDef); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && NetworkUser.AllParticipatingNetworkUsersReady() && SceneCatalog.mostRecentSceneDef == desiredSceneDef) + { + outer.SetNextState(new VoidEndingPlayCutscene()); + } + } + + public override void OnExit() + { + FadeToBlackManager.fadeCount--; + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingStart.cs b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingStart.cs new file mode 100644 index 0000000..5714e70 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GameOver/VoidEndingStart.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GameOver; + +public class VoidEndingStart : BaseGameOverControllerState +{ + [SerializeField] + public float duration; + + private bool hasSceneExited; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration && hasSceneExited) + { + outer.SetNextState(new VoidEndingFadeToBlack()); + } + } + + public override void OnEnter() + { + base.OnEnter(); + SceneExitController.onFinishExit += OnFinishSceneExit; + } + + public override void OnExit() + { + SceneExitController.onFinishExit -= OnFinishSceneExit; + base.OnExit(); + } + + private void OnFinishSceneExit(SceneExitController obj) + { + hasSceneExited = true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeEntityStates.cs b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeEntityStates.cs new file mode 100644 index 0000000..62ad30a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeEntityStates.cs @@ -0,0 +1,41 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Geode; + +public class GeodeEntityStates : EntityState +{ + protected GeodeController geodeController; + + protected GameObject cleansingIndicator; + + protected GameObject geodeModel; + + protected Renderer geodeTrunkRenderer; + + protected GameObject geodeBase; + + protected GameObject geodeIdleVFX; + + protected int sliceHeightNameId; + + public override void OnEnter() + { + base.OnEnter(); + geodeController = base.gameObject.GetComponent(); + ChildLocator component = base.gameObject.GetComponent(); + cleansingIndicator = component.FindChildGameObject(0); + geodeModel = component.FindChildGameObject(1); + geodeBase = component.FindChildGameObject(2); + geodeIdleVFX = component.FindChildGameObject(3); + geodeTrunkRenderer = geodeModel.GetComponent(); + geodeTrunkRenderer.material.EnableKeyword("_SLICEHEIGHT"); + int propertyIndex = geodeTrunkRenderer.material.shader.FindPropertyIndex("_SliceHeight"); + sliceHeightNameId = geodeTrunkRenderer.material.shader.GetPropertyNameId(propertyIndex); + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeInert.cs b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeInert.cs new file mode 100644 index 0000000..408bfd3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeInert.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +namespace EntityStates.Geode; + +public class GeodeInert : GeodeEntityStates +{ + [SerializeField] + public float reactivationDuration; + + public override void OnEnter() + { + base.OnEnter(); + cleansingIndicator.SetActive(value: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= reactivationDuration && geodeController.ShouldRegenerate) + { + outer.SetNextState(new GeodeRegenerate()); + } + else if (!geodeController.ShouldRegenerate) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeRegenerate.cs b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeRegenerate.cs new file mode 100644 index 0000000..475c15c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeRegenerate.cs @@ -0,0 +1,48 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Geode; + +public class GeodeRegenerate : GeodeEntityStates +{ + private new float age; + + public override void OnEnter() + { + base.OnEnter(); + geodeModel.SetActive(value: true); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + age += Time.deltaTime; + float printThreshold = geodeController.printCurve.Evaluate(age / geodeController.printTime); + SetPrintThreshold(printThreshold); + if (age >= geodeController.idleVFXRegenerationTimer && !geodeIdleVFX.activeInHierarchy) + { + geodeIdleVFX.SetActive(value: true); + } + if (age >= geodeController.printTime) + { + if (NetworkServer.active) + { + geodeController.SetAvailable(activeState: true); + } + outer.SetNextState(new GeodeEntityStates()); + } + } + + private void SetPrintThreshold(float sample) + { + float num = 1f - sample; + float value = sample * geodeController.maxPrintHeight + num * geodeController.startingPrintHeight; + geodeTrunkRenderer.material.SetFloat(sliceHeightNameId, value); + } + + public override void OnExit() + { + base.OnExit(); + age = 0f; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeShatter.cs b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeShatter.cs new file mode 100644 index 0000000..f5f474f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Geode/GeodeShatter.cs @@ -0,0 +1,174 @@ +using System.Collections.Generic; +using HG; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Geode; + +public class GeodeShatter : GeodeEntityStates +{ + private SphereSearch sphereSearch; + + private List hitHurtBoxes; + + private bool cleansingActive = true; + + private float stopWatch; + + protected bool rewardGiven; + + [Tooltip("The prefab to use for the reward pickup.")] + [SerializeField] + public GameObject rewardPickupPrefab; + + [SerializeField] + public PickupDropTable rewardDropTable; + + [SerializeField] + public int rewardOptionCount = 1; + + [SerializeField] + public ItemTier rewardDisplayTier; + + [SerializeField] + public Vector3 rewardOffset; + + [SerializeField] + public float cleansingDuration = 6f; + + [SerializeField] + public float cleansingTicksPerSecond = 1.5f; + + protected Xoroshiro128Plus rng; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/GeodeShatterVFX"), new EffectData + { + origin = base.gameObject.transform.position + }, transmit: false); + Util.PlaySound("Play_env_meridian_geode_activate", base.gameObject); + Util.PlaySound("Play_env_meridian_geode_active_loop", base.gameObject); + cleansingIndicator.SetActive(value: true); + sphereSearch = new SphereSearch(); + CharacterBody characterBody = geodeController.lastInteractor?.GetComponent(); + if (!geodeController.ShouldRegenerate) + { + geodeBase.SetActive(value: false); + } + geodeTrunkRenderer.material.SetFloat(sliceHeightNameId, geodeController.startingPrintHeight); + geodeIdleVFX.SetActive(value: false); + geodeModel.SetActive(value: false); + if (!NetworkServer.active) + { + return; + } + if ((bool)characterBody && characterBody.HasBuff(DLC2Content.Buffs.GeodeBuff) && geodeController.ShouldDropReward) + { + rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong); + RemoveGeodeBuffFromAllPlayers(); + int participatingPlayerCount = Run.instance.participatingPlayerCount; + if (!(base.gameObject == null) && !(rewardDropTable == null) && participatingPlayerCount != 0 && participatingPlayerCount > 0 && (bool)base.gameObject && (bool)rewardDropTable && !rewardGiven) + { + rewardGiven = true; + int num = participatingPlayerCount; + float angle = 360f / (float)num; + Vector3 vector = Quaternion.AngleAxis(Random.Range(0, 360), Vector3.up) * (Vector3.up * 40f + Vector3.forward * 5f); + Quaternion quaternion = Quaternion.AngleAxis(angle, Vector3.up); + Vector3 position = base.gameObject.transform.position + rewardOffset; + int num2 = 0; + while (num2 < num) + { + GenericPickupController.CreatePickupInfo pickupInfo = default(GenericPickupController.CreatePickupInfo); + pickupInfo.pickupIndex = PickupCatalog.FindPickupIndex(rewardDisplayTier); + pickupInfo.pickerOptions = PickupPickerController.GenerateOptionsFromDropTable(rewardOptionCount, rewardDropTable, rng); + pickupInfo.rotation = Quaternion.identity; + pickupInfo.prefabOverride = rewardPickupPrefab; + PickupDropletController.CreatePickupDroplet(pickupInfo, position, vector); + num2++; + vector = quaternion * vector; + } + } + } + else + { + RemoveGeodeBuffFromAllPlayers(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= cleansingDuration) + { + cleansingActive = false; + Util.PlaySound("Stop_env_meridian_geode_active_loop", base.gameObject); + outer.SetNextState(new GeodeInert()); + } + else + { + if (!cleansingActive) + { + return; + } + stopWatch += Time.deltaTime; + if (stopWatch > 1f / cleansingTicksPerSecond && sphereSearch != null) + { + stopWatch -= 1f / cleansingTicksPerSecond; + if (NetworkServer.active) + { + HandleCleanseNearbyPlayers(); + } + } + } + } + + private void HandleCleanseNearbyPlayers() + { + hitHurtBoxes = CollectionPool>.RentCollection(); + SearchForPlayers(hitHurtBoxes); + for (int i = 0; i < hitHurtBoxes.Count; i++) + { + HurtBox hurtBox = hitHurtBoxes[i]; + CharacterBody body = hurtBox.healthComponent.body; + bool isPlayerControlled = body.isPlayerControlled; + if ((bool)hurtBox && hurtBox.healthComponent.alive && isPlayerControlled && !body.HasBuff(DLC2Content.Buffs.GeodeBuff)) + { + Util.PlaySound("Play_env_meridian_geode_cleanse_debuff", body.gameObject); + Util.CleanseBody(body, removeDebuffs: true, removeBuffs: false, removeCooldownBuffs: true, removeDots: true, removeStun: true, removeNearbyProjectiles: true); + hurtBox.healthComponent.AddBarrier(hurtBox.healthComponent.fullHealth * geodeController.barrierToHealthPercentage); + body.AddBuff(DLC2Content.Buffs.GeodeBuff); + } + } + } + + protected void RemoveGeodeBuffFromAllPlayers() + { + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + CharacterBody currentBody = instance.networkUser.GetCurrentBody(); + if (currentBody.HasBuff(DLC2Content.Buffs.GeodeBuff)) + { + currentBody.RemoveBuff(DLC2Content.Buffs.GeodeBuff); + } + } + } + + protected void SearchForPlayers(List dest) + { + TeamMask mask = default(TeamMask); + mask.AddTeam(TeamIndex.Player); + sphereSearch.mask = LayerIndex.entityPrecise.mask; + sphereSearch.origin = base.gameObject.transform.position; + sphereSearch.radius = geodeController.geodeBuffRadius; + sphereSearch.queryTriggerInteraction = QueryTriggerInteraction.UseGlobal; + sphereSearch.RefreshCandidates(); + sphereSearch.FilterCandidatesByHurtBoxTeam(mask); + sphereSearch.OrderCandidatesByDistance(); + sphereSearch.FilterCandidatesByDistinctHurtBoxEntities(); + sphereSearch.GetHurtBoxes(dest); + sphereSearch.ClearCandidates(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarDetonator/Detonate.cs b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarDetonator/Detonate.cs new file mode 100644 index 0000000..07b6054 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarDetonator/Detonate.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GlobalSkills.LunarDetonator; + +public class Detonate : BaseState +{ + private class DetonationController + { + public HurtBox[] detonationTargets; + + public CharacterBody characterBody; + + public float damageStat; + + public bool isCrit; + + public float interval; + + private int i; + + private float timer; + + private bool _active; + + public bool active + { + get + { + return _active; + } + set + { + if (_active != value) + { + _active = value; + if (_active) + { + RoR2Application.onFixedUpdate += FixedUpdate; + } + else + { + RoR2Application.onFixedUpdate -= FixedUpdate; + } + } + } + } + + private void FixedUpdate() + { + if (!characterBody || !characterBody.healthComponent || !characterBody.healthComponent.alive) + { + active = false; + return; + } + timer -= Time.deltaTime; + if (!(timer <= 0f)) + { + return; + } + for (timer = interval; i < detonationTargets.Length; i++) + { + try + { + HurtBox a = null; + Util.Swap(ref a, ref detonationTargets[i]); + if (DoDetonation(a)) + { + break; + } + } + catch (Exception message) + { + Debug.LogError(message); + } + } + if (i >= detonationTargets.Length) + { + active = false; + } + } + + private bool DoDetonation(HurtBox targetHurtBox) + { + if (!targetHurtBox) + { + return false; + } + HealthComponent healthComponent = targetHurtBox.healthComponent; + if (!healthComponent) + { + return false; + } + CharacterBody body = healthComponent.body; + if (!body) + { + return false; + } + if (body.GetBuffCount(RoR2Content.Buffs.LunarDetonationCharge) <= 0) + { + return false; + } + LunarDetonatorOrb lunarDetonatorOrb = new LunarDetonatorOrb(); + lunarDetonatorOrb.origin = characterBody.corePosition; + lunarDetonatorOrb.target = targetHurtBox; + lunarDetonatorOrb.attacker = characterBody.gameObject; + lunarDetonatorOrb.baseDamage = damageStat * baseDamageCoefficient; + lunarDetonatorOrb.damagePerStack = damageStat * damageCoefficientPerStack; + lunarDetonatorOrb.damageColorIndex = DamageColorIndex.Default; + lunarDetonatorOrb.isCrit = isCrit; + lunarDetonatorOrb.procChainMask = default(ProcChainMask); + lunarDetonatorOrb.procCoefficient = 1f; + lunarDetonatorOrb.detonationEffectPrefab = detonationEffectPrefab; + lunarDetonatorOrb.travelSpeed = 120f; + lunarDetonatorOrb.orbEffectPrefab = orbEffectPrefab; + OrbManager.instance.AddOrb(lunarDetonatorOrb); + return true; + } + } + + public static float baseDuration; + + public static float baseDamageCoefficient; + + public static float damageCoefficientPerStack; + + public static float procCoefficient; + + public static float detonationInterval; + + public static GameObject detonationEffectPrefab; + + public static GameObject orbEffectPrefab; + + public static GameObject enterEffectPrefab; + + public static string enterSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string playbackRateParam; + + private float duration; + + private HurtBox[] detonationTargets; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + EffectManager.SimpleImpactEffect(enterEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: false); + Util.PlaySound(enterSoundString, base.gameObject); + if (NetworkServer.active) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.filterByDistinctEntity = true; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.maxDistanceFilter = float.PositiveInfinity; + bullseyeSearch.minDistanceFilter = 0f; + bullseyeSearch.minAngleFilter = 0f; + bullseyeSearch.maxAngleFilter = 180f; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.teamMaskFilter = TeamMask.GetUnprotectedTeams(GetTeam()); + bullseyeSearch.searchOrigin = base.characterBody.corePosition; + bullseyeSearch.viewer = null; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + IEnumerable results = bullseyeSearch.GetResults(); + detonationTargets = results.ToArray(); + new DetonationController + { + characterBody = base.characterBody, + interval = detonationInterval, + detonationTargets = detonationTargets, + damageStat = damageStat, + isCrit = RollCrit(), + active = true + }; + } + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/ChargeLunarSecondary.cs b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/ChargeLunarSecondary.cs new file mode 100644 index 0000000..afae770 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/ChargeLunarSecondary.cs @@ -0,0 +1,26 @@ +using EntityStates.Mage.Weapon; +using UnityEngine; + +namespace EntityStates.GlobalSkills.LunarNeedle; + +public class ChargeLunarSecondary : BaseChargeBombState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string playbackRateParam; + + protected override BaseThrowBombState GetNextState() + { + return new ThrowLunarSecondary(); + } + + protected override void PlayChargeAnimation() + { + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, base.duration); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/FireLunarNeedle.cs b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/FireLunarNeedle.cs new file mode 100644 index 0000000..763bdfd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/FireLunarNeedle.cs @@ -0,0 +1,80 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.GlobalSkills.LunarNeedle; + +public class FireLunarNeedle : BaseSkillState +{ + public static float baseDuration; + + public static float damageCoefficient; + + public static GameObject projectilePrefab; + + public static float recoilAmplitude; + + public static float spreadBloomValue; + + public static GameObject muzzleFlashEffectPrefab; + + public static string fireSound; + + public static float maxSpread; + + private float duration; + + [SerializeField] + public string animationLayerName = "Gesture, Override"; + + [SerializeField] + public string animationStateName = "FireLunarNeedle"; + + [SerializeField] + public string playbackRateParam = "FireLunarNeedle.playbackRate"; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, maxSpread, 1f, 1f); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = aimRay.origin; + fireProjectileInfo.rotation = Quaternion.LookRotation(aimRay.direction); + fireProjectileInfo.crit = base.characterBody.RollCrit(); + fireProjectileInfo.damage = base.characterBody.damage * damageCoefficient; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.force = 0f; + fireProjectileInfo.useFuseOverride = false; + fireProjectileInfo.useSpeedOverride = false; + fireProjectileInfo.target = null; + fireProjectileInfo.projectilePrefab = projectilePrefab; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + AddRecoil(-0.4f * recoilAmplitude, -0.8f * recoilAmplitude, -0.3f * recoilAmplitude, 0.3f * recoilAmplitude); + base.characterBody.AddSpreadBloom(spreadBloomValue); + StartAimMode(); + EffectManager.SimpleMuzzleFlash(muzzleFlashEffectPrefab, base.gameObject, "Head", transmit: false); + Util.PlaySound(fireSound, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/ThrowLunarSecondary.cs b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/ThrowLunarSecondary.cs new file mode 100644 index 0000000..8f1376f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.LunarNeedle/ThrowLunarSecondary.cs @@ -0,0 +1,35 @@ +using EntityStates.Mage.Weapon; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.GlobalSkills.LunarNeedle; + +public class ThrowLunarSecondary : BaseThrowBombState +{ + [SerializeField] + public float minSpeed; + + [SerializeField] + public float maxSpeed; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string playbackRateParam; + + protected override void PlayThrowAnimation() + { + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, duration); + } + + protected override void ModifyProjectile(ref FireProjectileInfo projectileInfo) + { + projectileInfo.speedOverride = Util.Remap(charge, 0f, 1f, minSpeed, maxSpeed); + projectileInfo.useSpeedOverride = true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.WoundSlash/WoundSlash.cs b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.WoundSlash/WoundSlash.cs new file mode 100644 index 0000000..0a0e455 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GlobalSkills.WoundSlash/WoundSlash.cs @@ -0,0 +1,81 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GlobalSkills.WoundSlash; + +public class WoundSlash : BaseSkillState +{ + public static float blastRadius; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static float blastProcCoefficient; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject slashEffectPrefab; + + public static float slashEffectOffset; + + public static float baseDuration; + + public static string soundString; + + public static float shortHopVelocity; + + private float duration => baseDuration / attackSpeedStat; + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + Vector3 vector = base.characterBody.corePosition + aimRay.direction * slashEffectOffset; + Util.PlaySound(soundString, base.gameObject); + EffectData effectData = new EffectData + { + origin = vector, + rotation = Util.QuaternionSafeLookRotation(aimRay.direction) + }; + EffectManager.SpawnEffect(slashEffectPrefab, effectData, transmit: true); + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.baseDamage = blastDamageCoefficient * damageStat; + blastAttack.baseForce = blastForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.crit = RollCrit(); + blastAttack.damageType = DamageType.Generic; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.inflictor = base.gameObject; + blastAttack.position = vector; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = blastProcCoefficient; + blastAttack.radius = blastRadius; + blastAttack.teamIndex = base.teamComponent.teamIndex; + blastAttack.impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab); + blastAttack.Fire(); + } + if (base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.velocity.y = Mathf.Max(base.characterMotor.velocity.y, shortHopVelocity); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GoldGat/BaseGoldGatState.cs b/ilspy_dump/ror2_csproj/EntityStates.GoldGat/BaseGoldGatState.cs new file mode 100644 index 0000000..396e1d2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GoldGat/BaseGoldGatState.cs @@ -0,0 +1,112 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GoldGat; + +public class BaseGoldGatState : EntityState +{ + protected NetworkedBodyAttachment networkedBodyAttachment; + + protected GameObject bodyGameObject; + + protected CharacterBody body; + + protected ChildLocator gunChildLocator; + + protected Animator gunAnimator; + + protected Transform gunTransform; + + protected CharacterMaster bodyMaster; + + protected EquipmentSlot bodyEquipmentSlot; + + protected InputBankTest bodyInputBank; + + protected AimAnimator bodyAimAnimator; + + public bool shouldFire; + + private bool linkedToDisplay; + + public override void OnEnter() + { + base.OnEnter(); + networkedBodyAttachment = GetComponent(); + if (!networkedBodyAttachment) + { + return; + } + bodyGameObject = networkedBodyAttachment.attachedBodyObject; + body = networkedBodyAttachment.attachedBody; + if ((bool)bodyGameObject) + { + bodyMaster = body.master; + bodyInputBank = bodyGameObject.GetComponent(); + bodyEquipmentSlot = body.equipmentSlot; + ModelLocator component = body.GetComponent(); + if ((bool)component) + { + bodyAimAnimator = component.modelTransform.GetComponent(); + } + LinkToDisplay(); + } + } + + private void LinkToDisplay() + { + if (linkedToDisplay || !bodyEquipmentSlot) + { + return; + } + gunTransform = bodyEquipmentSlot.FindActiveEquipmentDisplay(); + if ((bool)gunTransform) + { + gunChildLocator = gunTransform.GetComponentInChildren(); + if ((bool)gunChildLocator && (bool)base.modelLocator) + { + base.modelLocator.modelTransform = gunChildLocator.transform; + gunAnimator = GetModelAnimator(); + linkedToDisplay = true; + } + } + } + + public override void FixedUpdate() + { + base.Update(); + if (base.isAuthority && (bool)bodyInputBank) + { + if (bodyInputBank.activateEquipment.justPressed) + { + shouldFire = !shouldFire; + } + if (body.inventory.GetItemCount(RoR2Content.Items.AutoCastEquipment) > 0) + { + shouldFire = true; + } + } + LinkToDisplay(); + if ((bool)bodyAimAnimator && (bool)gunAnimator) + { + bodyAimAnimator.UpdateAnimatorParameters(gunAnimator, -45f, 45f, 0f, 0f); + } + } + + protected bool CheckReturnToIdle() + { + if (!base.isAuthority) + { + return false; + } + if (((bool)bodyMaster && bodyMaster.money == 0) || !shouldFire) + { + outer.SetNextState(new GoldGatIdle + { + shouldFire = shouldFire + }); + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GoldGat/GoldGatFire.cs b/ilspy_dump/ror2_csproj/EntityStates.GoldGat/GoldGatFire.cs new file mode 100644 index 0000000..6a6b8f7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GoldGat/GoldGatFire.cs @@ -0,0 +1,120 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GoldGat; + +public class GoldGatFire : BaseGoldGatState +{ + public static float minFireFrequency; + + public static float maxFireFrequency; + + public static float minSpread; + + public static float maxSpread; + + public static float windUpDuration; + + public static float force; + + public static float damageCoefficient; + + public static float procCoefficient; + + public static string attackSoundString; + + public static GameObject tracerEffectPrefab; + + public static GameObject impactEffectPrefab; + + public static GameObject muzzleFlashEffectPrefab; + + public static int baseMoneyCostPerBullet; + + public static string windUpSoundString; + + public static string windUpRTPC; + + public float totalStopwatch; + + private float stopwatch; + + private float fireFrequency; + + private uint loopSoundID; + + private static int CrankplaybackRateParamHash = Animator.StringToHash("Crank.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + loopSoundID = Util.PlaySound(windUpSoundString, base.gameObject); + FireBullet(); + } + + private void FireBullet() + { + body.SetAimTimer(2f); + float t = Mathf.Clamp01(totalStopwatch / windUpDuration); + fireFrequency = Mathf.Lerp(minFireFrequency, maxFireFrequency, t); + float num = Mathf.Lerp(minSpread, maxSpread, t); + Util.PlaySound(attackSoundString, base.gameObject); + int num2 = (int)((float)baseMoneyCostPerBullet * (1f + ((float)TeamManager.instance.GetTeamLevel(bodyMaster.teamIndex) - 1f) * 0.25f)); + if (base.isAuthority) + { + Transform aimOriginTransform = body.aimOriginTransform; + if ((bool)gunChildLocator) + { + gunChildLocator.FindChild("Muzzle"); + } + if ((bool)aimOriginTransform) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = networkedBodyAttachment.attachedBodyObject; + bulletAttack.aimVector = bodyInputBank.aimDirection; + bulletAttack.origin = bodyInputBank.aimOrigin; + bulletAttack.falloffModel = BulletAttack.FalloffModel.DefaultBullet; + bulletAttack.force = force; + bulletAttack.damage = body.damage * damageCoefficient; + bulletAttack.damageColorIndex = DamageColorIndex.Item; + bulletAttack.bulletCount = 1u; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = num; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(body.crit, bodyMaster); + bulletAttack.procCoefficient = procCoefficient; + bulletAttack.muzzleName = "Muzzle"; + bulletAttack.weapon = base.gameObject; + bulletAttack.Fire(); + gunAnimator?.Play("Fire"); + } + } + if (NetworkServer.active) + { + bodyMaster.money = (uint)Mathf.Max(0f, bodyMaster.money - num2); + } + gunAnimator?.SetFloat(CrankplaybackRateParamHash, fireFrequency); + EffectManager.SimpleMuzzleFlash(muzzleFlashEffectPrefab, base.gameObject, "Muzzle", transmit: false); + } + + public override void Update() + { + base.Update(); + float deltaTime = Time.deltaTime; + totalStopwatch += deltaTime; + stopwatch += deltaTime; + AkSoundEngine.SetRTPCValueByPlayingID(windUpRTPC, Mathf.InverseLerp(minFireFrequency, maxFireFrequency, fireFrequency) * 100f, loopSoundID); + if (!CheckReturnToIdle() && stopwatch > 1f / fireFrequency) + { + stopwatch = 0f; + FireBullet(); + } + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(loopSoundID); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GoldGat/GoldGatIdle.cs b/ilspy_dump/ror2_csproj/EntityStates.GoldGat/GoldGatIdle.cs new file mode 100644 index 0000000..73d8d16 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GoldGat/GoldGatIdle.cs @@ -0,0 +1,30 @@ +using RoR2; + +namespace EntityStates.GoldGat; + +public class GoldGatIdle : BaseGoldGatState +{ + public static string windDownSoundString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(windDownSoundString, base.gameObject); + } + + public override void Update() + { + base.Update(); + if ((bool)gunAnimator) + { + gunAnimator.SetFloat("Crank.playbackRate", 0f, 1f, GetDeltaTime()); + } + if (base.isAuthority && shouldFire && bodyMaster.money != 0 && bodyEquipmentSlot.stock > 0) + { + outer.SetNextState(new GoldGatFire + { + shouldFire = shouldFire + }); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/ChargeLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/ChargeLaser.cs new file mode 100644 index 0000000..2bacab2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/ChargeLaser.cs @@ -0,0 +1,198 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GolemMonster; + +public class ChargeLaser : BaseState +{ + public static float baseDuration = 3f; + + public static float laserMaxWidth = 0.2f; + + public static GameObject effectPrefab; + + public static GameObject laserPrefab; + + public static string attackSoundString; + + private float duration; + + private uint chargePlayID; + + private GameObject chargeEffect; + + private GameObject laserEffect; + + private LineRenderer laserLineComponent; + + private Vector3 laserDirection; + + private Vector3 visualEndPosition; + + private float flashTimer; + + private bool laserOn; + + protected EffectManagerHelper _efh_Charge; + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargePlayID = 0u; + chargeEffect = null; + laserLineComponent = null; + laserDirection = Vector3.zero; + visualEndPosition = Vector3.zero; + flashTimer = 0f; + laserOn = false; + _efh_Charge = null; + } + + public override void OnEnter() + { + base.OnEnter(); + SetAIUpdateFrequency(alwaysUpdate: true); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + chargePlayID = Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleLaser"); + if ((bool)transform) + { + if ((bool)effectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _efh_Charge = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffect = _efh_Charge.gameObject; + } + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)laserPrefab && laserEffect == null) + { + laserEffect = Object.Instantiate(laserPrefab, transform.position, transform.rotation); + } + if (laserEffect != null) + { + if (!laserEffect.activeInHierarchy) + { + laserEffect.SetActive(value: true); + } + if (laserEffect.transform.parent != transform) + { + laserEffect.transform.parent = transform; + } + laserLineComponent = laserEffect.GetComponent(); + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + flashTimer = 0f; + laserOn = true; + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(chargePlayID); + base.OnExit(); + SetAIUpdateFrequency(alwaysUpdate: false); + if ((bool)chargeEffect) + { + if (!EffectManager.UsePools) + { + EntityState.Destroy(chargeEffect); + } + else if (_efh_Charge != null && _efh_Charge.OwningPool != null) + { + if (!_efh_Charge.OwningPool.IsObjectInPool(_efh_Charge)) + { + _efh_Charge.OwningPool.ReturnObject(_efh_Charge); + } + } + else + { + if (_efh_Charge != null) + { + Debug.LogFormat("ChargeLaser has no owning pool {0} {1}", base.gameObject.name, base.gameObject.GetInstanceID()); + } + EntityState.Destroy(chargeEffect); + } + } + if ((bool)laserEffect && laserEffect.activeInHierarchy) + { + laserEffect.SetActive(value: false); + } + } + + public override void Update() + { + base.Update(); + if (!laserEffect || !laserLineComponent) + { + return; + } + float num = 1000f; + Ray aimRay = GetAimRay(); + Vector3 position = laserEffect.transform.parent.position; + Vector3 point = aimRay.GetPoint(num); + laserDirection = point - position; + if (Physics.Raycast(aimRay, out var hitInfo, num, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask)) + { + point = hitInfo.point; + } + laserLineComponent.SetPosition(0, position); + laserLineComponent.SetPosition(1, point); + float num2; + if (duration - base.age > 0.5f) + { + num2 = base.age / duration; + } + else + { + flashTimer -= Time.deltaTime; + if (flashTimer <= 0f) + { + laserOn = !laserOn; + flashTimer = 1f / 30f; + } + num2 = (laserOn ? 1f : 0f); + } + num2 *= laserMaxWidth; + laserLineComponent.startWidth = num2; + laserLineComponent.endWidth = num2; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireLaser fireLaser = new FireLaser(); + fireLaser.laserDirection = laserDirection; + outer.SetNextState(fireLaser); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/ClapState.cs b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/ClapState.cs new file mode 100644 index 0000000..c280a41 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/ClapState.cs @@ -0,0 +1,162 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GolemMonster; + +public class ClapState : BaseState +{ + public static float duration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + private BlastAttack attack; + + public static string attackSoundString; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + private GameObject leftHandChargeEffect; + + private GameObject rightHandChargeEffect; + + private EffectManagerHelper _emh_leftHandChargeEffect; + + private EffectManagerHelper _emh_rightHandChargeEffect; + + public override void Reset() + { + base.Reset(); + modelAnimator = null; + modelTransform = null; + hasAttacked = false; + leftHandChargeEffect = null; + rightHandChargeEffect = null; + if (attack != null) + { + attack.Reset(); + } + _emh_leftHandChargeEffect = null; + _emh_rightHandChargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("Body", "Clap", "Clap.playbackRate", duration, 0.1f); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + GameObject gameObject = LegacyResourcesAPI.Load("Prefabs/GolemClapCharge"); + Transform transform = component.FindChild("HandL"); + Transform transform2 = component.FindChild("HandR"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(gameObject)) + { + leftHandChargeEffect = Object.Instantiate(gameObject, transform); + } + else + { + _emh_leftHandChargeEffect = EffectManager.GetAndActivatePooledEffect(gameObject, transform, inResetLocal: true); + leftHandChargeEffect = _emh_leftHandChargeEffect.gameObject; + } + } + if ((bool)transform2) + { + if (!EffectManager.ShouldUsePooledEffect(gameObject)) + { + rightHandChargeEffect = Object.Instantiate(gameObject, transform2); + return; + } + _emh_rightHandChargeEffect = EffectManager.GetAndActivatePooledEffect(gameObject, transform2, inResetLocal: true); + rightHandChargeEffect = _emh_rightHandChargeEffect.gameObject; + } + } + + protected void DestroyChargeEffects() + { + if (_emh_leftHandChargeEffect != null && _emh_leftHandChargeEffect.OwningPool != null) + { + _emh_leftHandChargeEffect.OwningPool.ReturnObject(_emh_leftHandChargeEffect); + } + else + { + EntityState.Destroy(leftHandChargeEffect); + } + leftHandChargeEffect = null; + _emh_leftHandChargeEffect = null; + if (_emh_rightHandChargeEffect != null && _emh_rightHandChargeEffect.OwningPool != null) + { + _emh_rightHandChargeEffect.OwningPool.ReturnObject(_emh_rightHandChargeEffect); + } + else + { + EntityState.Destroy(rightHandChargeEffect); + } + rightHandChargeEffect = null; + _emh_rightHandChargeEffect = null; + } + + public override void OnExit() + { + DestroyChargeEffects(); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("Clap.hitBoxActive") > 0.5f && !hasAttacked) + { + if (base.isAuthority && (bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("ClapZone"); + if ((bool)transform) + { + attack = new BlastAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * damageCoefficient; + attack.baseForce = forceMagnitude; + attack.position = transform.position; + attack.radius = radius; + attack.attackerFiltering = AttackerFiltering.NeverHitSelf; + attack.Fire(); + } + } + } + hasAttacked = true; + DestroyChargeEffects(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/DeathState.cs new file mode 100644 index 0000000..905a533 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/DeathState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GolemMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialDeathExplosionPrefab; + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("Head"); + if ((bool)transform && (bool)initialDeathExplosionPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(initialDeathExplosionPrefab)) + { + Object.Instantiate(initialDeathExplosionPrefab, transform.position, Quaternion.identity).transform.parent = transform; + } + else + { + EffectManager.GetAndActivatePooledEffect(initialDeathExplosionPrefab, transform.position, Quaternion.identity, transform); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/FireLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/FireLaser.cs new file mode 100644 index 0000000..668ad27 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/FireLaser.cs @@ -0,0 +1,121 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GolemMonster; + +public class FireLaser : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float blastRadius; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public Vector3 laserDirection; + + private float duration; + + private Ray modifiedAimRay; + + private static int FireLaserStateHash = Animator.StringToHash("FireLaser"); + + private static int FireLaserParamHash = Animator.StringToHash("FireLaser.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modifiedAimRay = GetAimRay(); + modifiedAimRay.direction = laserDirection; + GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + Util.PlaySound(attackSoundString, base.gameObject); + string text = "MuzzleLaser"; + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + PlayAnimation("Gesture", FireLaserStateHash, FireLaserParamHash, duration); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, text, transmit: false); + } + if (!base.isAuthority) + { + return; + } + float num = 1000f; + Vector3 vector = modifiedAimRay.origin + modifiedAimRay.direction * num; + if (Physics.Raycast(modifiedAimRay, out var hitInfo, num, LayerIndex.CommonMasks.laser)) + { + vector = hitInfo.point; + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = force * 0.2f; + blastAttack.position = vector; + blastAttack.radius = blastRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.SweetSpot; + blastAttack.bonusForce = force * modifiedAimRay.direction; + blastAttack.Fire(); + _ = modifiedAimRay.origin; + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + int childIndex = component.FindChildIndex(text); + if ((bool)tracerEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = vector, + start = modifiedAimRay.origin + }; + effectData.SetChildLocatorTransformReference(base.gameObject, childIndex); + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + EffectManager.SpawnEffect(hitEffectPrefab, effectData, transmit: true); + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/SpawnState.cs new file mode 100644 index 0000000..8cef9fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GolemMonster/SpawnState.cs @@ -0,0 +1,45 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GolemMonster; + +public class SpawnState : GenericCharacterSpawnState +{ + private GameObject eyeGameObject; + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + modelTransform.GetComponent().enabled = true; + } + eyeGameObject = FindModelChild("Eye")?.gameObject; + if ((bool)eyeGameObject) + { + eyeGameObject.SetActive(value: false); + } + if (base.characterBody.HasBuff(DLC2Content.Buffs.EliteAurelionite)) + { + PrintController component = base.modelLocator.modelTransform.gameObject.GetComponent(); + component.enabled = false; + component.printTime = duration; + component.startingPrintHeight = -101.78f; + component.maxPrintHeight = -93f; + component.startingPrintBias = 2f; + component.maxPrintBias = 0.95f; + component.disableWhenFinished = true; + component.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + component.enabled = true; + } + } + + public override void OnExit() + { + if (!outer.destroying && (bool)eyeGameObject) + { + eyeGameObject.SetActive(value: true); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSun.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSun.cs new file mode 100644 index 0000000..97edf0d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSun.cs @@ -0,0 +1,122 @@ +using RoR2; +using RoR2.Navigation; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GrandParent; + +public class ChannelSun : ChannelSunBase +{ + public static string animLayerName; + + public static string animStateName; + + public static GameObject sunPrefab; + + public static float sunPrefabDiameter = 10f; + + public static float sunPlacementMinDistance = 100f; + + public static float sunPlacementIdealAltitudeBonus = 200f; + + private GameObject sunInstance; + + public Vector3? sunSpawnPosition; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animLayerName, animStateName); + if (NetworkServer.active) + { + sunSpawnPosition = sunSpawnPosition ?? FindSunSpawnPosition(base.transform.position); + if (sunSpawnPosition.HasValue) + { + sunInstance = CreateSun(sunSpawnPosition.Value); + } + } + } + + public override void OnExit() + { + if (NetworkServer.active && (bool)sunInstance) + { + sunInstance.GetComponent().ownerObject = null; + sunInstance = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && !IsKeyDownAuthority()) + { + outer.SetNextState(new ChannelSunEnd()); + } + } + + private GameObject CreateSun(Vector3 sunSpawnPosition) + { + GameObject obj = Object.Instantiate(sunPrefab, sunSpawnPosition, Quaternion.identity); + obj.GetComponent().ownerObject = base.gameObject; + NetworkServer.Spawn(obj); + return obj; + } + + private static Vector3? FindSunNodePosition(Vector3 searchOrigin) + { + NodeGraph airNodes = SceneInfo.instance.airNodes; + NodeGraph.NodeIndex nodeIndex = airNodes.FindClosestNodeWithFlagConditions(searchOrigin, HullClassification.Golem, NodeFlags.None, NodeFlags.None, preventOverhead: false); + if (nodeIndex == NodeGraph.NodeIndex.invalid) + { + return null; + } + float num = sunPlacementMinDistance; + float num2 = num * num; + _ = NodeGraph.NodeIndex.invalid; + float num3 = 0f; + NodeGraphSpider nodeGraphSpider = new NodeGraphSpider(airNodes, HullMask.Golem); + nodeGraphSpider.AddNodeForNextStep(nodeIndex); + int num4 = 0; + int i = 0; + while (nodeGraphSpider.PerformStep()) + { + num4++; + for (; i < nodeGraphSpider.collectedSteps.Count; i++) + { + NodeGraphSpider.StepInfo stepInfo = nodeGraphSpider.collectedSteps[i]; + airNodes.GetNodePosition(stepInfo.node, out var position); + float sqrMagnitude = (position - searchOrigin).sqrMagnitude; + if (sqrMagnitude > num3) + { + num3 = sqrMagnitude; + _ = stepInfo.node; + if (num3 >= num2) + { + return position; + } + } + } + } + return null; + } + + public static Vector3? FindSunSpawnPosition(Vector3 searchOrigin) + { + Vector3? vector = FindSunNodePosition(searchOrigin); + if (vector.HasValue) + { + Vector3 value = vector.Value; + float num = sunPlacementIdealAltitudeBonus; + float num2 = sunPrefabDiameter * 0.5f; + if (Physics.Raycast(value, Vector3.up, out var hitInfo, sunPlacementIdealAltitudeBonus + num2, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + num = Mathf.Clamp(hitInfo.distance - num2, 0f, num); + } + value.y += num; + return value; + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunBase.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunBase.cs new file mode 100644 index 0000000..aafb5a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunBase.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +namespace EntityStates.GrandParent; + +public abstract class ChannelSunBase : BaseSkillState +{ + [SerializeField] + public GameObject handVfxPrefab; + + public static string leftHandVfxTargetNameInChildLocator; + + public static string rightHandVfxTargetNameInChildLocator; + + private GameObject leftHandVfxInstance; + + private GameObject rightHandVfxInstance; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)handVfxPrefab) + { + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + CreateVfxInstanceForHand(modelChildLocator, leftHandVfxTargetNameInChildLocator, ref leftHandVfxInstance); + CreateVfxInstanceForHand(modelChildLocator, rightHandVfxTargetNameInChildLocator, ref rightHandVfxInstance); + } + } + } + + public override void OnExit() + { + DestroyVfxInstance(ref leftHandVfxInstance); + DestroyVfxInstance(ref rightHandVfxInstance); + base.OnExit(); + } + + protected void CreateVfxInstanceForHand(ChildLocator childLocator, string nameInChildLocator, ref GameObject dest) + { + Transform transform = childLocator.FindChild(nameInChildLocator); + if ((bool)transform) + { + dest = Object.Instantiate(handVfxPrefab, transform); + } + else + { + dest = null; + } + } + + protected void DestroyVfxInstance(ref GameObject vfxInstance) + { + EntityState.Destroy(vfxInstance); + vfxInstance = null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunEnd.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunEnd.cs new file mode 100644 index 0000000..e107da8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunEnd.cs @@ -0,0 +1,30 @@ +namespace EntityStates.GrandParent; + +public class ChannelSunEnd : ChannelSunBase +{ + public static string animLayerName; + + public static string animStateName; + + public static string animPlaybackRateParam; + + public static float baseDuration; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animLayerName, animStateName, animPlaybackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunStart.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunStart.cs new file mode 100644 index 0000000..d8d80c6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParent/ChannelSunStart.cs @@ -0,0 +1,125 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GrandParent; + +public class ChannelSunStart : ChannelSunBase +{ + public static string animLayerName; + + public static string animStateName; + + public static string animPlaybackRateParam; + + public static string beginSoundName; + + public static float baseDuration; + + public static GameObject beamVfxPrefab; + + private float duration; + + private Vector3? sunSpawnPosition; + + private ParticleSystem leftHandBeamParticleSystem; + + private ParticleSystem rightHandBeamParticleSystem; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animLayerName, animStateName, animPlaybackRateParam, duration); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + } + if (base.isAuthority) + { + sunSpawnPosition = sunSpawnPosition ?? ChannelSun.FindSunSpawnPosition(base.transform.position); + } + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && sunSpawnPosition.HasValue) + { + CreateBeamEffect(modelChildLocator, ChannelSunBase.leftHandVfxTargetNameInChildLocator, sunSpawnPosition.Value, ref leftHandBeamParticleSystem); + CreateBeamEffect(modelChildLocator, ChannelSunBase.rightHandVfxTargetNameInChildLocator, sunSpawnPosition.Value, ref rightHandBeamParticleSystem); + } + if (beginSoundName != null) + { + Util.PlaySound(beginSoundName, base.gameObject); + } + } + + public override void OnExit() + { + EndBeamEffect(ref leftHandBeamParticleSystem); + EndBeamEffect(ref rightHandBeamParticleSystem); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new ChannelSun + { + activatorSkillSlot = base.activatorSkillSlot, + sunSpawnPosition = sunSpawnPosition + }); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(sunSpawnPosition.HasValue); + if (sunSpawnPosition.HasValue) + { + writer.Write(sunSpawnPosition.Value); + } + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + sunSpawnPosition = null; + if (reader.ReadBoolean()) + { + sunSpawnPosition = reader.ReadVector3(); + } + } + + private void CreateBeamEffect(ChildLocator childLocator, string nameInChildLocator, Vector3 targetPosition, ref ParticleSystem dest) + { + Transform transform = childLocator.FindChild(nameInChildLocator); + if ((bool)transform) + { + ChildLocator component = Object.Instantiate(beamVfxPrefab, transform).GetComponent(); + component.FindChild("EndPoint").SetPositionAndRotation(targetPosition, Quaternion.identity); + Transform transform2 = component.FindChild("BeamParticles"); + dest = transform2.GetComponent(); + } + else + { + dest = null; + } + } + + private void EndBeamEffect(ref ParticleSystem particleSystem) + { + if ((bool)particleSystem) + { + ParticleSystem.MainModule main = particleSystem.main; + main.loop = false; + particleSystem.Stop(); + } + particleSystem = null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/DeathState.cs new file mode 100644 index 0000000..acdb829 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/DeathState.cs @@ -0,0 +1,7 @@ +using EntityStates.ParentMonster; + +namespace EntityStates.GrandParentBoss; + +public class DeathState : EntityStates.ParentMonster.DeathState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/FireSecondaryProjectile.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/FireSecondaryProjectile.cs new file mode 100644 index 0000000..b636d03 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/FireSecondaryProjectile.cs @@ -0,0 +1,98 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.GrandParentBoss; + +public class FireSecondaryProjectile : BaseState +{ + [SerializeField] + public float baseDuration = 3f; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public string muzzleName = "SecondaryProjectileMuzzle"; + + [SerializeField] + public string animationStateName = "FireSecondaryProjectile"; + + [SerializeField] + public string playbackRateParam = "FireSecondaryProjectile.playbackRate"; + + [SerializeField] + public string animationLayerName = "Body"; + + [SerializeField] + public float baseFireDelay; + + private float duration; + + private float fireDelay; + + private bool hasFired; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + fireDelay = baseFireDelay / attackSpeedStat; + if (fireDelay <= Time.fixedDeltaTime * 2f) + { + Fire(); + } + PlayCrossfade(animationLayerName, animationStateName, playbackRateParam, duration, 0.2f); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!hasFired && base.fixedAge >= fireDelay) + { + Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void Fire() + { + hasFired = true; + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (!base.isAuthority || !projectilePrefab) + { + return; + } + Ray aimRay = GetAimRay(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + aimRay.origin = component.FindChild(muzzleName).transform.position; + } + } + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/GroundSwipe.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/GroundSwipe.cs new file mode 100644 index 0000000..b831fd0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/GroundSwipe.cs @@ -0,0 +1,219 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.GrandParentBoss; + +public class GroundSwipe : BasicMeleeAttack, SteppedSkillDef.IStepSetter +{ + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float baseChargeStartDelay; + + [SerializeField] + public float baseFireProjectileDelay; + + [SerializeField] + public float projectileDamageCoefficient; + + [SerializeField] + public float projectileForce; + + [SerializeField] + public float maxBullseyeDistance; + + [SerializeField] + public float maxBullseyeAngle; + + [SerializeField] + public float minProjectileDistance; + + [SerializeField] + public float maxProjectileDistance; + + [SerializeField] + public float projectileHorizontalSpeed; + + [SerializeField] + public string chargeSoundName; + + [SerializeField] + public string hitBoxGroupNameLeft; + + [SerializeField] + public string animationLayerName = "Body"; + + [SerializeField] + public string muzzleNameLeft = "SecondaryProjectileMuzzle"; + + [SerializeField] + public string muzzleNameRight = "SecondaryProjectileMuzzle"; + + [SerializeField] + public string animationStateNameLeft = "FireSecondaryProjectile"; + + [SerializeField] + public string animationStateNameRight = "FireSecondaryProjectile"; + + [SerializeField] + public string playbackRateParam = "GroundSwipe.playbackRate"; + + private GameObject chargeEffectInstance; + + private bool hasFired; + + private float chargeStartDelay; + + private float fireProjectileDelay; + + private int step; + + protected ChildLocator childLocator { get; private set; } + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + step = i; + } + + public override void OnEnter() + { + base.OnEnter(); + hasFired = false; + chargeStartDelay = baseChargeStartDelay / attackSpeedStat; + fireProjectileDelay = baseFireProjectileDelay / attackSpeedStat; + childLocator = GetModelChildLocator(); + } + + public override void OnExit() + { + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + protected override void PlayAnimation() + { + PlayCrossfade(animationLayerName, GetAnimationStateName(), playbackRateParam, duration, 1f); + } + + public string GetMuzzleName() + { + if (step % 2 == 0) + { + return muzzleNameLeft; + } + return muzzleNameRight; + } + + public string GetAnimationStateName() + { + if (step % 2 == 0) + { + return animationStateNameLeft; + } + return animationStateNameRight; + } + + public override string GetHitBoxGroupName() + { + if (step % 2 == 0) + { + return hitBoxGroupNameLeft; + } + return hitBoxGroupName; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!chargeEffectInstance && (bool)childLocator && base.fixedAge >= chargeStartDelay) + { + Transform transform = childLocator.FindChild(GetMuzzleName()) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + if ((bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + ObjectScaleCurve component2 = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + if ((bool)component2) + { + component2.timeMax = duration; + } + } + if (chargeSoundName != null) + { + Util.PlaySound(chargeSoundName, base.gameObject); + } + } + } + if (base.isAuthority && !hasFired && (bool)projectilePrefab && base.fixedAge >= fireProjectileDelay) + { + hasFired = true; + Ray aimRay = GetAimRay(); + Ray ray = aimRay; + Transform transform2 = childLocator.FindChild(GetMuzzleName()); + if ((bool)transform2) + { + ray.origin = transform2.position; + } + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.searchOrigin = base.characterBody.corePosition; + bullseyeSearch.searchDirection = base.characterBody.corePosition; + bullseyeSearch.maxDistanceFilter = maxBullseyeDistance; + bullseyeSearch.maxAngleFilter = maxBullseyeAngle; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + Vector3? vector = null; + RaycastHit hitInfo; + if ((bool)hurtBox) + { + vector = hurtBox.transform.position; + } + else if (Physics.Raycast(aimRay, out hitInfo, float.PositiveInfinity, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + vector = hitInfo.point; + } + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * projectileDamageCoefficient; + fireProjectileInfo.force = projectileForce; + fireProjectileInfo.crit = RollCrit(); + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + if (vector.HasValue) + { + Vector3 vector2 = vector.Value - ray.origin; + Vector2 vector3 = new Vector2(vector2.x, vector2.z); + float magnitude = vector3.magnitude; + Vector2 vector4 = vector3 / magnitude; + magnitude = Mathf.Clamp(magnitude, minProjectileDistance, maxProjectileDistance); + float y = Trajectory.CalculateInitialYSpeed(magnitude / projectileHorizontalSpeed, vector2.y); + Vector3 direction = new Vector3(vector4.x * projectileHorizontalSpeed, y, vector4.y * projectileHorizontalSpeed); + fireProjectileInfo2.speedOverride = direction.magnitude; + ray.direction = direction; + } + else + { + fireProjectileInfo2.speedOverride = projectileHorizontalSpeed; + } + fireProjectileInfo2.rotation = Util.QuaternionSafeLookRotation(ray.direction); + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/Offspring.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/Offspring.cs new file mode 100644 index 0000000..f079436 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/Offspring.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GrandParentBoss; + +public class Offspring : BaseState +{ + [SerializeField] + public GameObject SpawnerPodsPrefab; + + public static float randomRadius = 8f; + + public static float maxRange = 9999f; + + private Animator animator; + + private ChildLocator childLocator; + + private Transform modelTransform; + + private float duration; + + public static float baseDuration = 3.5f; + + public static string attackSoundString; + + private float summonInterval; + + private static float summonDuration = 3.26f; + + public static int maxSummonCount = 5; + + private float summonTimer; + + private bool isSummoning; + + private int summonCount; + + public static GameObject spawnEffect; + + private static int SpawnPodWarnStateHash = Animator.StringToHash("SpawnPodWarn"); + + private static int SpawnPodWarnParamHash = Animator.StringToHash("spawnPodWarn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + duration = baseDuration; + Util.PlaySound(attackSoundString, base.gameObject); + summonInterval = summonDuration / (float)maxSummonCount; + isSummoning = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (isSummoning) + { + summonTimer += GetDeltaTime(); + if (NetworkServer.active && summonTimer > 0f && summonCount < maxSummonCount) + { + summonCount++; + summonTimer -= summonInterval; + SpawnPods(); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void SpawnPods() + { + Vector3 zero = Vector3.zero; + Ray aimRay = GetAimRay(); + aimRay.origin += UnityEngine.Random.insideUnitSphere * randomRadius; + if (Physics.Raycast(aimRay, out var hitInfo, (int)LayerIndex.world.mask)) + { + zero = hitInfo.point; + } + zero = base.transform.position; + Transform transform = FindTargetFarthest(zero, GetTeam()); + if ((bool)transform) + { + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscParentPod"), new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Approximate, + minDistance = 3f, + maxDistance = 20f, + spawnOnTarget = transform + }, RoR2Application.rng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult spawnResult) + { + Inventory inventory = spawnResult.spawnedInstance.GetComponent().inventory; + Inventory inventory2 = base.characterBody.inventory; + inventory.CopyEquipmentFrom(inventory2); + }); + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + PlayAnimation("Body", SpawnPodWarnStateHash, SpawnPodWarnParamHash, duration); + } + } + + private Transform FindTargetFarthest(Vector3 point, TeamIndex myTeam) + { + float num = 0f; + Transform result = null; + TeamMask enemyTeams = TeamMask.GetEnemyTeams(myTeam); + for (TeamIndex teamIndex = TeamIndex.Neutral; teamIndex < TeamIndex.Count; teamIndex++) + { + if (!enemyTeams.HasTeam(teamIndex)) + { + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(teamIndex); + for (int i = 0; i < teamMembers.Count; i++) + { + float num2 = Vector3.Magnitude(teamMembers[i].transform.position - point); + if (num2 > num && num2 < maxRange) + { + num = num2; + result = teamMembers[i].transform; + } + } + } + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/PortalFist.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/PortalFist.cs new file mode 100644 index 0000000..331ed6a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/PortalFist.cs @@ -0,0 +1,111 @@ +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.GrandParentBoss; + +public class PortalFist : BaseState +{ + public static float baseDuration; + + public static GameObject portalInEffectPrefab; + + public static GameObject portalOutEffectPrefab; + + public static string portalMuzzleString; + + public static string fistMeshChildLocatorString; + + public static string fistBoneChildLocatorString; + + public static string mecanimFistVisibilityString; + + public static float fistOverlayDuration; + + public static Material fistOverlayMaterial; + + public static float targetSearchMaxDistance; + + private GameObject fistMeshGameObject; + + private GameObject fistBoneGameObject; + + private GameObject fistTargetGameObject; + + private string fistTargetMuzzleString; + + private Animator modelAnimator; + + private CharacterModel characterModel; + + private float duration; + + private bool fistWasOutOfPortal = true; + + public override void OnEnter() + { + base.OnEnter(); + fistMeshGameObject = FindModelChild(fistMeshChildLocatorString).gameObject; + fistBoneGameObject = FindModelChild(fistBoneChildLocatorString).gameObject; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + } + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "PortalFist", "PortalFist.playbackRate", duration, 0.3f); + Transform transform = FindModelChild("PortalFistTargetRig"); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.searchOrigin = base.characterBody.corePosition; + bullseyeSearch.searchDirection = base.characterBody.corePosition; + bullseyeSearch.maxDistanceFilter = targetSearchMaxDistance; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); + bullseyeSearch.teamMaskFilter.RemoveTeam(TeamIndex.Neutral); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)hurtBox) + { + transform.position = hurtBox.transform.position; + fistTargetMuzzleString = $"PortalFistTargetPosition{Random.Range(1, 5).ToString()}"; + fistTargetGameObject = FindModelChild(fistTargetMuzzleString).gameObject; + } + } + + public override void Update() + { + base.Update(); + bool flag = modelAnimator.GetFloat(mecanimFistVisibilityString) > 0.5f; + if (flag != fistWasOutOfPortal) + { + fistWasOutOfPortal = flag; + EffectManager.SimpleMuzzleFlash(flag ? portalOutEffectPrefab : portalInEffectPrefab, base.gameObject, portalMuzzleString, transmit: false); + EffectManager.SimpleMuzzleFlash(flag ? portalOutEffectPrefab : portalInEffectPrefab, base.gameObject, fistTargetMuzzleString, transmit: false); + if ((bool)characterModel && (bool)fistOverlayMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(characterModel.gameObject); + temporaryOverlayInstance.duration = fistOverlayDuration; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = fistOverlayMaterial; + temporaryOverlayInstance.inspectorCharacterModel = characterModel; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + } + if ((bool)fistTargetGameObject && !flag) + { + fistBoneGameObject.transform.SetPositionAndRotation(fistTargetGameObject.transform.position, fistTargetGameObject.transform.rotation); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/PortalJump.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/PortalJump.cs new file mode 100644 index 0000000..06a3c99 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/PortalJump.cs @@ -0,0 +1,237 @@ +using System.Linq; +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.GrandParentBoss; + +public class PortalJump : BaseState +{ + private BullseyeSearch enemyFinder; + + public static float duration = 3f; + + public static float retreatDuration = 2.433f; + + public static float emergeDuration = 2.933f; + + public static float portalScaleDuration = 2f; + + public static float effectsDuration = 2f; + + private bool retreatDone; + + private bool teleported; + + private bool canMoveDuringTeleport; + + private bool hasEmerged; + + private HurtBox foundBullseye; + + public static float telezoneRadius; + + public static float skillDistance = 2000f; + + private float stopwatch; + + private Vector3 destinationPressence = Vector3.zero; + + private Vector3 startPressence = Vector3.zero; + + private Transform modelTransform; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + public static GameObject jumpInEffectPrefab; + + public static GameObject jumpOutEffectPrefab; + + public static Vector3 teleportOffset; + + private GrandparentEnergyFXController FXController; + + private static int RetreatStateHash = Animator.StringToHash("Retreat"); + + private static int RetreatParamHash = Animator.StringToHash("retreat.playbackRate"); + + private static int EmergeStateHash = Animator.StringToHash("Emerge"); + + private static int EmergeParamHash = Animator.StringToHash("emerge.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + PlayAnimation("Body", RetreatStateHash, RetreatParamHash, retreatDuration); + EffectData effectData = new EffectData + { + origin = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild("Portal").position + }; + EffectManager.SpawnEffect(jumpInEffectPrefab, effectData, transmit: true); + } + FXController = base.characterBody.GetComponent(); + if ((bool)FXController) + { + FXController.portalObject = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild("Portal").GetComponentInChildren() + .gameObject; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= retreatDuration && !retreatDone) + { + retreatDone = true; + if ((bool)FXController) + { + ScaleObject(FXController.portalObject, scaleUp: false); + } + } + if (stopwatch >= retreatDuration + portalScaleDuration && !teleported) + { + teleported = true; + canMoveDuringTeleport = true; + if ((bool)FXController) + { + FXController.portalObject.GetComponent().enabled = false; + } + DoTeleport(); + } + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.velocity = Vector3.zero; + } + if (canMoveDuringTeleport) + { + SetPosition(Vector3.Lerp(startPressence, destinationPressence, stopwatch / duration)); + } + if (stopwatch >= retreatDuration + portalScaleDuration + duration && canMoveDuringTeleport) + { + canMoveDuringTeleport = false; + if ((bool)FXController) + { + FXController.portalObject.transform.position = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild("Portal").position; + ScaleObject(FXController.portalObject, scaleUp: true); + } + } + if (stopwatch >= retreatDuration + portalScaleDuration * 2f + duration && !hasEmerged) + { + hasEmerged = true; + if ((bool)FXController) + { + FXController.portalObject.GetComponent().enabled = false; + } + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + PlayAnimation("Body", EmergeStateHash, EmergeParamHash, duration); + EffectData effectData = new EffectData + { + origin = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild("Portal").position + }; + EffectManager.SpawnEffect(jumpOutEffectPrefab, effectData, transmit: true); + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = true; + } + } + } + if (stopwatch >= retreatDuration + portalScaleDuration * 2f + duration + emergeDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void DoTeleport() + { + Ray aimRay = GetAimRay(); + enemyFinder = new BullseyeSearch(); + enemyFinder.maxDistanceFilter = skillDistance; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.filterByLoS = false; + enemyFinder.sortMode = BullseyeSearch.SortMode.Distance; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + enemyFinder.RefreshCandidates(); + foundBullseye = enemyFinder.GetResults().LastOrDefault(); + modelTransform = GetModelTransform(); + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + Vector3 vector = base.inputBank.moveVector * skillDistance; + destinationPressence = base.transform.position; + startPressence = base.transform.position; + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + Vector3 position = startPressence + vector; + if ((bool)foundBullseye) + { + position = foundBullseye.transform.position; + } + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNode(position, base.characterBody.hullClassification); + groundNodes.GetNodePosition(nodeIndex, out destinationPressence); + destinationPressence += base.transform.position - base.characterBody.footPosition; + } + + private void SetPosition(Vector3 newPosition) + { + if ((bool)base.characterMotor) + { + base.characterMotor.Motor.SetPositionAndRotation(newPosition, Quaternion.identity); + } + } + + private void ScaleObject(GameObject objectToScaleDown, bool scaleUp) + { + float valueEnd = (scaleUp ? 1f : 0f); + float valueStart = (scaleUp ? 0f : 1f); + ObjectScaleCurve component = objectToScaleDown.GetComponent(); + component.timeMax = portalScaleDuration; + component.curveX = AnimationCurve.Linear(0f, valueStart, 1f, valueEnd); + component.curveY = AnimationCurve.Linear(0f, valueStart, 1f, valueEnd); + component.curveZ = AnimationCurve.Linear(0f, valueStart, 1f, valueEnd); + component.overallCurve = AnimationCurve.EaseInOut(0f, valueStart, 1f, valueEnd); + component.enabled = true; + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/SpawnState.cs new file mode 100644 index 0000000..579e73f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/SpawnState.cs @@ -0,0 +1,119 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GrandParentBoss; + +public class SpawnState : GenericCharacterSpawnState +{ + public static GameObject preSpawnEffect; + + public static string preSpawnEffectMuzzle; + + public static float preSpawnDuration; + + public static GameObject spawnEffect; + + public static string spawnEffectMuzzle; + + public static Material spawnOverlayMaterial; + + public static float spawnOverlayDuration; + + public static float blastAttackRadius; + + public static float blastAttackForce; + + public static float blastAttackBonusForce; + + private bool hasSpawned; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private bool preSpawnIsDone; + + private static int Spawn1StateHash = Animator.StringToHash("Spawn1"); + + private static int Spawn1ParamHash = Animator.StringToHash("Spawn1.playbackRate"); + + private bool isInvisible; + + public override void OnEnter() + { + base.OnEnter(); + characterModel = base.modelLocator.modelTransform.GetComponent(); + hurtboxGroup = base.modelLocator.modelTransform.GetComponent(); + ToggleInvisibility(newInvisible: true); + if ((bool)preSpawnEffect) + { + EffectManager.SimpleMuzzleFlash(preSpawnEffect, base.gameObject, preSpawnEffectMuzzle, transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!preSpawnIsDone && base.fixedAge > preSpawnDuration) + { + preSpawnIsDone = true; + ToggleInvisibility(newInvisible: false); + PlayAnimation("Body", Spawn1StateHash, Spawn1ParamHash, duration - preSpawnDuration); + if ((bool)spawnEffect) + { + EffectManager.SimpleMuzzleFlash(spawnEffect, base.gameObject, spawnEffectMuzzle, transmit: false); + } + if (base.isAuthority) + { + BlastAttack obj = new BlastAttack + { + attacker = base.gameObject, + inflictor = base.gameObject + }; + obj.teamIndex = TeamComponent.GetObjectTeam(obj.attacker); + obj.position = base.characterBody.corePosition; + obj.procCoefficient = 1f; + obj.radius = blastAttackRadius; + obj.baseForce = blastAttackForce; + obj.bonusForce = Vector3.up * blastAttackBonusForce; + obj.baseDamage = 0f; + obj.falloffModel = BlastAttack.FalloffModel.Linear; + obj.damageColorIndex = DamageColorIndex.Item; + obj.attackerFiltering = AttackerFiltering.NeverHitSelf; + obj.Fire(); + } + if ((bool)characterModel && (bool)spawnOverlayMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(characterModel.gameObject); + temporaryOverlayInstance.duration = spawnOverlayDuration; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = spawnOverlayMaterial; + temporaryOverlayInstance.inspectorCharacterModel = characterModel; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + } + } + + private void ToggleInvisibility(bool newInvisible) + { + if (isInvisible != newInvisible) + { + isInvisible = newInvisible; + if ((bool)characterModel) + { + characterModel.invisibilityCount += (isInvisible ? 1 : (-1)); + } + if ((bool)hurtboxGroup) + { + hurtboxGroup.hurtBoxesDeactivatorCounter += (isInvisible ? 1 : (-1)); + } + } + } + + public override void OnExit() + { + ToggleInvisibility(newInvisible: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/SpiritPull.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/SpiritPull.cs new file mode 100644 index 0000000..22f773d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentBoss/SpiritPull.cs @@ -0,0 +1,322 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.GrandParentBoss; + +public class SpiritPull : BaseState +{ + private BullseyeSearch enemyFinder; + + public static float lockOnAngle; + + private Vector3 teleporterIndicatorInstance; + + private Transform modelTransform; + + public static float pullTimer; + + public static float zoneRadius; + + public static float initialDelay; + + private float duration = 4f; + + public static float maxRange; + + public static string teleportZoneString; + + public static GameObject teleportZoneEffect; + + public static GameObject playerTeleportEffect; + + public static float effectsDuration = 2f; + + public static float playerTeleportEffectsDuration = 1f; + + private bool effectsDone; + + private bool gatheredVictims; + + private bool teleported; + + private float stopwatch; + + private List Startpositions; + + private List Endpositions; + + public static int stacks; + + private List results = new List(); + + private HurtBox foundBullseye; + + private BullseyeSearch search; + + private GameObject spiritPullLocationObject; + + public static string indicatorOnPlayerSoundLoop; + + public static string indicatorOnPlayerSoundStop; + + public static string teleportedPlayerSound; + + public override void OnEnter() + { + base.OnEnter(); + Startpositions = new List(); + Endpositions = new List(); + Ray aimRay = GetAimRay(); + modelTransform = GetModelTransform(); + enemyFinder = new BullseyeSearch(); + enemyFinder.maxDistanceFilter = 2000f; + enemyFinder.maxAngleFilter = lockOnAngle; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.filterByLoS = false; + enemyFinder.sortMode = BullseyeSearch.SortMode.Distance; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + enemyFinder.RefreshCandidates(); + foundBullseye = enemyFinder.GetResults().LastOrDefault(); + _ = Vector3.zero; + if ((bool)foundBullseye) + { + teleporterIndicatorInstance = foundBullseye.transform.position; + if (Physics.Raycast(teleporterIndicatorInstance, Vector3.down, out var hitInfo, 500f, LayerIndex.world.mask)) + { + teleporterIndicatorInstance = hitInfo.point; + _ = teleporterIndicatorInstance; + } + EffectData effectData = new EffectData + { + origin = teleporterIndicatorInstance, + rotation = teleportZoneEffect.transform.rotation, + scale = zoneRadius * 2f + }; + EffectManager.SpawnEffect(teleportZoneEffect, effectData, transmit: true); + if (spiritPullLocationObject == null) + { + spiritPullLocationObject = new GameObject(); + } + spiritPullLocationObject.transform.position = effectData.origin; + Util.PlaySound(indicatorOnPlayerSoundLoop, spiritPullLocationObject); + } + } + + private Transform FindTargetFarthest(Vector3 point, TeamIndex enemyTeam) + { + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(enemyTeam); + float num = 0f; + Transform result = null; + for (int i = 0; i < teamMembers.Count; i++) + { + float num2 = Vector3.SqrMagnitude(teamMembers[i].transform.position - point); + if (num2 > num && num2 < maxRange) + { + num = num2; + result = teamMembers[i].transform; + } + } + return result; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + pullTimer -= Time.deltaTime; + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= effectsDuration && !gatheredVictims) + { + effectsDone = true; + gatheredVictims = true; + GetPlayersInsideTeleportZone(); + } + if (stopwatch >= effectsDuration + playerTeleportEffectsDuration && !teleported) + { + teleported = true; + TeleportPlayers(); + } + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.velocity = Vector3.zero; + } + if (effectsDone) + { + SetPositions(); + } + if (stopwatch >= effectsDuration + playerTeleportEffectsDuration + duration && base.isAuthority) + { + effectsDone = false; + outer.SetNextStateToMain(); + } + } + + private void GetPlayersInsideTeleportZone() + { + Startpositions.Clear(); + Endpositions.Clear(); + if (!foundBullseye) + { + return; + } + for (int i = 0; i < stacks; i++) + { + search = new BullseyeSearch(); + search.filterByLoS = false; + search.maxDistanceFilter = zoneRadius; + search.searchOrigin = new Vector3(teleporterIndicatorInstance.x, teleporterIndicatorInstance.y + zoneRadius * (float)i, teleporterIndicatorInstance.z); + search.sortMode = BullseyeSearch.SortMode.Distance; + search.teamMaskFilter = TeamMask.allButNeutral; + search.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + search.RefreshCandidates(); + search.queryTriggerInteraction = QueryTriggerInteraction.Collide; + for (int j = 0; j < search.GetResults().ToList().Count; j++) + { + if (!results.Contains(search.GetResults().ToList()[j])) + { + results.Add(search.GetResults().ToList()[j]); + } + } + } + if (results.Count <= 0) + { + return; + } + for (int k = 0; k < results.Count; k++) + { + HurtBox hurtBox = results[k]; + Transform transform = hurtBox.healthComponent.body.modelLocator.modelTransform; + EffectData effectData = new EffectData + { + origin = hurtBox.healthComponent.body.footPosition + }; + EffectManager.SpawnEffect(playerTeleportEffect, effectData, transmit: true); + if ((bool)transform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(transform.gameObject); + temporaryOverlayInstance.duration = 0.6f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matGrandparentTeleportFlash"); + temporaryOverlayInstance.AddToCharacterModel(transform.GetComponent()); + } + } + } + + private void TeleportPlayers() + { + if (results.Count <= 0) + { + return; + } + for (int i = 0; i < results.Count; i++) + { + HurtBox hurtBox = results[i]; + CharacterModel component = hurtBox.healthComponent.body.modelLocator.modelTransform.GetComponent(); + HurtBoxGroup component2 = hurtBox.healthComponent.body.modelLocator.modelTransform.GetComponent(); + Startpositions.Add(hurtBox.transform.position); + if ((bool)component2) + { + int hurtBoxesDeactivatorCounter = component2.hurtBoxesDeactivatorCounter + 1; + component2.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)component) + { + component.invisibilityCount++; + } + CharacterMotor component3 = hurtBox.healthComponent.gameObject.GetComponent(); + if ((bool)component3) + { + component3.enabled = false; + } + duration = initialDelay; + GameObject teleportEffectPrefab = Run.instance.GetTeleportEffectPrefab(base.gameObject); + if ((bool)teleportEffectPrefab) + { + Object.Instantiate(teleportEffectPrefab, base.gameObject.transform.position, Quaternion.identity); + } + Util.PlaySound(teleportedPlayerSound, hurtBox.gameObject); + base.characterMotor.velocity = Vector3.zero; + Vector3 position = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild(teleportZoneString).position; + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNode(position, base.characterBody.hullClassification); + groundNodes.GetNodePosition(nodeIndex, out position); + position += hurtBox.healthComponent.body.transform.position - hurtBox.healthComponent.body.footPosition; + position = new Vector3(position.x, position.y + 0.1f, position.z); + Endpositions.Add(position); + } + } + + private void SetPositions() + { + if (results.Count <= 0) + { + return; + } + for (int i = 0; i < results.Count; i++) + { + CharacterMotor component = results[i].healthComponent.gameObject.GetComponent(); + if ((bool)component) + { + Vector3 position = Vector3.Lerp(Startpositions[i], Endpositions[i], stopwatch / duration); + component.Motor.SetPositionAndRotation(position, Quaternion.identity); + } + } + } + + public override void OnExit() + { + base.OnExit(); + Util.PlaySound(indicatorOnPlayerSoundStop, spiritPullLocationObject); + if (results.Count <= 0) + { + return; + } + for (int i = 0; i < results.Count; i++) + { + HurtBox hurtBox = results[i]; + CharacterModel component = hurtBox.healthComponent.body.modelLocator.modelTransform.GetComponent(); + HurtBoxGroup component2 = hurtBox.healthComponent.body.modelLocator.modelTransform.GetComponent(); + Transform transform = hurtBox.healthComponent.body.modelLocator.modelTransform; + if ((bool)transform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(transform.gameObject); + temporaryOverlayInstance.duration = 0.6f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matGrandparentTeleportFlash"); + temporaryOverlayInstance.AddToCharacterModel(transform.GetComponent()); + } + EffectData effectData = new EffectData + { + origin = hurtBox.healthComponent.body.footPosition + }; + EffectManager.SpawnEffect(playerTeleportEffect, effectData, transmit: true); + if ((bool)component2) + { + int hurtBoxesDeactivatorCounter = component2.hurtBoxesDeactivatorCounter - 1; + component2.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)component) + { + component.invisibilityCount--; + } + CharacterMotor component3 = hurtBox.healthComponent.gameObject.GetComponent(); + if ((bool)component3) + { + component3.enabled = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunBase.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunBase.cs new file mode 100644 index 0000000..dd69742 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunBase.cs @@ -0,0 +1,46 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GrandParentSun; + +public abstract class GrandParentSunBase : BaseState +{ + [SerializeField] + public GameObject enterEffectPrefab; + + protected GrandParentSunController sunController { get; private set; } + + protected Transform vfxRoot { get; private set; } + + protected virtual bool shouldEnableSunController => false; + + protected abstract float desiredVfxScale { get; } + + public override void OnEnter() + { + base.OnEnter(); + sunController = GetComponent(); + sunController.enabled = shouldEnableSunController; + vfxRoot = base.transform.Find("VfxRoot"); + if ((bool)enterEffectPrefab) + { + EffectManager.SimpleImpactEffect(enterEffectPrefab, vfxRoot.position, Vector3.up, transmit: false); + } + SetVfxScale(desiredVfxScale); + } + + public override void Update() + { + base.Update(); + SetVfxScale(desiredVfxScale); + } + + private void SetVfxScale(float newScale) + { + newScale = Mathf.Max(newScale, 0.01f); + if ((bool)vfxRoot && vfxRoot.transform.localScale.x != newScale) + { + vfxRoot.transform.localScale = new Vector3(newScale, newScale, newScale); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunDeath.cs new file mode 100644 index 0000000..1d6232a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunDeath.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GrandParentSun; + +public class GrandParentSunDeath : GrandParentSunBase +{ + public static float baseDuration; + + private float duration; + + protected override float desiredVfxScale => 1f - Mathf.Clamp01(base.age / duration); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + NetworkServer.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunMain.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunMain.cs new file mode 100644 index 0000000..8e668a2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunMain.cs @@ -0,0 +1,27 @@ +using RoR2; + +namespace EntityStates.GrandParentSun; + +public class GrandParentSunMain : GrandParentSunBase +{ + private GenericOwnership ownership; + + protected override bool shouldEnableSunController => true; + + protected override float desiredVfxScale => 1f; + + public override void OnEnter() + { + base.OnEnter(); + ownership = GetComponent(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && !ownership.ownerObject) + { + outer.SetNextState(new GrandParentSunDeath()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunSpawn.cs b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunSpawn.cs new file mode 100644 index 0000000..59bd94b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GrandParentSun/GrandParentSunSpawn.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace EntityStates.GrandParentSun; + +public class GrandParentSunSpawn : GrandParentSunBase +{ + public static float baseDuration; + + private float duration; + + protected override float desiredVfxScale => Mathf.Clamp01(base.age / duration); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new GrandParentSunMain()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/FireHook.cs b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/FireHook.cs new file mode 100644 index 0000000..36df2e1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/FireHook.cs @@ -0,0 +1,81 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GravekeeperBoss; + +public class FireHook : BaseState +{ + public static float baseDuration = 3f; + + public static string soundString; + + public static string muzzleString; + + public static float projectileDamageCoefficient; + + public static GameObject muzzleflashEffectPrefab; + + public static GameObject projectilePrefab; + + public static float spread; + + public static int projectileCount; + + public static float projectileForce; + + private float duration; + + private Animator modelAnimator; + + public override void OnEnter() + { + base.OnEnter(); + base.fixedAge = 0f; + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayCrossfade("Body", "FireHook", "FireHook.playbackRate", duration, 0.03f); + } + ChildLocator component = modelAnimator.GetComponent(); + if ((bool)component) + { + component.FindChild(muzzleString); + } + Util.PlayAttackSpeedSound(soundString, base.gameObject, attackSpeedStat); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + Ray aimRay = GetAimRay(); + if (NetworkServer.active) + { + FireSingleHook(aimRay, 0f, 0f); + for (int i = 0; i < projectileCount; i++) + { + float bonusPitch = Random.Range(0f - spread, spread) / 2f; + float bonusYaw = Random.Range(0f - spread, spread) / 2f; + FireSingleHook(aimRay, bonusPitch, bonusYaw); + } + } + } + + private void FireSingleHook(Ray aimRay, float bonusPitch, float bonusYaw) + { + Vector3 forward = Util.ApplySpread(aimRay.direction, 0f, 0f, 1f, 1f, bonusYaw, bonusPitch); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * projectileDamageCoefficient, projectileForce, Util.CheckRoll(critStat, base.characterBody.master)); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/PrepHook.cs b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/PrepHook.cs new file mode 100644 index 0000000..7abbaa2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/PrepHook.cs @@ -0,0 +1,109 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GravekeeperBoss; + +public class PrepHook : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargeEffectPrefab; + + public static string muzzleString; + + public static string attackString; + + private float duration; + + private GameObject chargeInstance; + + private Animator modelAnimator; + + private EffectManagerHelper _emh_chargeInstance; + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeInstance = null; + modelAnimator = null; + _emh_chargeInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + base.fixedAge = 0f; + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayCrossfade("Body", "PrepHook", "PrepHook.playbackRate", duration, 0.5f); + modelAnimator.GetComponent().enabled = true; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.inputBank.aimDirection; + } + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(muzzleString); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance = _emh_chargeInstance.gameObject; + } + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + } + Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new FireHook()); + } + } + + public override void OnExit() + { + if ((bool)chargeInstance) + { + if (_emh_chargeInstance != null && _emh_chargeInstance.OwningPool != null) + { + _emh_chargeInstance.OwningPool.ReturnObject(_emh_chargeInstance); + } + else + { + EntityState.Destroy(chargeInstance); + } + chargeInstance = null; + _emh_chargeInstance = null; + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/SpawnState.cs new file mode 100644 index 0000000..368dba2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperBoss/SpawnState.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GravekeeperBoss; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "Root", transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GravekeeperMonster.Weapon/GravekeeperBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperMonster.Weapon/GravekeeperBarrage.cs new file mode 100644 index 0000000..0ff9804 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GravekeeperMonster.Weapon/GravekeeperBarrage.cs @@ -0,0 +1,117 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GravekeeperMonster.Weapon; + +public class GravekeeperBarrage : BaseState +{ + private float stopwatch; + + private float missileStopwatch; + + public static float baseDuration; + + public static string muzzleString; + + public static float missileSpawnFrequency; + + public static float missileSpawnDelay; + + public static float missileForce; + + public static float damageCoefficient; + + public static float maxSpread; + + public static GameObject projectilePrefab; + + public static GameObject muzzleflashPrefab; + + public static string jarEffectChildLocatorString; + + public static string jarOpenSoundString; + + public static string jarCloseSoundString; + + public static GameObject jarOpenEffectPrefab; + + public static GameObject jarCloseEffectPrefab; + + private ChildLocator childLocator; + + private static int BeginGravekeeperBarrageStateHash = Animator.StringToHash("BeginGravekeeperBarrage"); + + private static int EndGravekeeperBarrageStateHash = Animator.StringToHash("EndGravekeeperBarrage"); + + public override void OnEnter() + { + base.OnEnter(); + missileStopwatch -= missileSpawnDelay; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + if ((bool)childLocator) + { + childLocator.FindChild("JarEffectLoop").gameObject.SetActive(value: true); + } + } + PlayAnimation("Jar, Override", BeginGravekeeperBarrageStateHash); + EffectManager.SimpleMuzzleFlash(jarOpenEffectPrefab, base.gameObject, jarEffectChildLocatorString, transmit: false); + Util.PlaySound(jarOpenSoundString, base.gameObject); + base.characterBody.SetAimTimer(baseDuration + 2f); + } + + private void FireBlob(Ray projectileRay, float bonusPitch, float bonusYaw) + { + projectileRay.direction = Util.ApplySpread(projectileRay.direction, 0f, maxSpread, 1f, 1f, bonusYaw, bonusPitch); + EffectManager.SimpleMuzzleFlash(muzzleflashPrefab, base.gameObject, muzzleString, transmit: false); + if (NetworkServer.active) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, projectileRay.origin, Util.QuaternionSafeLookRotation(projectileRay.direction), base.gameObject, damageStat * damageCoefficient, missileForce, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + PlayCrossfade("Jar, Override", EndGravekeeperBarrageStateHash, 0.06f); + EffectManager.SimpleMuzzleFlash(jarCloseEffectPrefab, base.gameObject, jarEffectChildLocatorString, transmit: false); + Util.PlaySound(jarCloseSoundString, base.gameObject); + if ((bool)childLocator) + { + childLocator.FindChild("JarEffectLoop").gameObject.SetActive(value: false); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + missileStopwatch += deltaTime; + if (missileStopwatch >= 1f / missileSpawnFrequency) + { + missileStopwatch -= 1f / missileSpawnFrequency; + Transform transform = childLocator.FindChild(muzzleString); + if ((bool)transform) + { + Ray projectileRay = default(Ray); + projectileRay.origin = transform.position; + projectileRay.direction = GetAimRay().direction; + float maxDistance = 1000f; + if (Physics.Raycast(GetAimRay(), out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + projectileRay.direction = hitInfo.point - transform.position; + } + FireBlob(projectileRay, 0f, 0f); + } + } + if (stopwatch >= baseDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/ChargeCannons.cs b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/ChargeCannons.cs new file mode 100644 index 0000000..442204c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/ChargeCannons.cs @@ -0,0 +1,150 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GreaterWispMonster; + +public class ChargeCannons : BaseState +{ + [SerializeField] + public float baseDuration = 3f; + + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public string attackString; + + protected float duration; + + private GameObject chargeEffectLeft; + + private GameObject chargeEffectRight; + + private const float soundDuration = 2f; + + private uint soundID; + + private EffectManagerHelper _emh_chargeEffectLeft; + + private EffectManagerHelper _emh_chargeEffectRight; + + private static int ChargeCannonsStateHash = Animator.StringToHash("ChargeCannons"); + + private static int ChargeCannonsParamHash = Animator.StringToHash("ChargeCannons.playbackRate"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffectLeft = null; + chargeEffectRight = null; + _emh_chargeEffectLeft = null; + _emh_chargeEffectRight = null; + } + + public override void OnEnter() + { + base.OnEnter(); + soundID = Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat * (2f / baseDuration)); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + GetModelAnimator(); + PlayAnimation("Gesture", ChargeCannonsStateHash, ChargeCannonsParamHash, duration); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component && (bool)effectPrefab) + { + Transform transform = component.FindChild("MuzzleLeft"); + Transform transform2 = component.FindChild("MuzzleRight"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffectLeft = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectLeft = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffectLeft = _emh_chargeEffectLeft.gameObject; + } + chargeEffectLeft.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffectLeft.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)transform2) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffectRight = Object.Instantiate(effectPrefab, transform2.position, transform2.rotation); + } + else + { + _emh_chargeEffectRight = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform2.position, transform2.rotation); + chargeEffectRight = _emh_chargeEffectRight.gameObject; + } + chargeEffectRight.transform.parent = transform2; + ScaleParticleSystemDuration component3 = chargeEffectRight.GetComponent(); + if ((bool)component3) + { + component3.newDuration = duration; + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + if (base.fixedAge < duration - 0.1f) + { + AkSoundEngine.StopPlayingID(soundID); + } + PlayAnimation("Gesture", EmptyStateHash); + if (_emh_chargeEffectLeft != null && _emh_chargeEffectLeft.OwningPool != null) + { + _emh_chargeEffectLeft.OwningPool.ReturnObject(_emh_chargeEffectLeft); + } + else + { + EntityState.Destroy(chargeEffectLeft); + } + chargeEffectLeft = null; + _emh_chargeEffectLeft = null; + if (_emh_chargeEffectRight != null && _emh_chargeEffectRight.OwningPool != null) + { + _emh_chargeEffectRight.OwningPool.ReturnObject(_emh_chargeEffectRight); + } + else + { + EntityState.Destroy(chargeEffectRight); + } + chargeEffectRight = null; + _emh_chargeEffectRight = null; + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireCannons nextState = new FireCannons(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/DeathState.cs new file mode 100644 index 0000000..4e8afab --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/DeathState.cs @@ -0,0 +1,112 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GreaterWispMonster; + +public class DeathState : GenericCharacterDeath +{ + [SerializeField] + public GameObject initialEffect; + + [SerializeField] + public GameObject deathEffect; + + private static float duration = 2f; + + private GameObject initialEffectInstance; + + private bool spawnedEffect; + + private EffectData _effectData; + + protected EffectManagerHelper _efh_initializeEffectInstance; + + public override void Reset() + { + base.Reset(); + initialEffectInstance = null; + spawnedEffect = false; + if (_effectData != null) + { + _effectData.Reset(); + } + _efh_initializeEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + if (!base.modelLocator) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("Mask"); + transform.gameObject.SetActive(value: true); + transform.GetComponent().timeMax = duration; + if ((bool)initialEffect) + { + if (!EffectManager.ShouldUsePooledEffect(initialEffect)) + { + initialEffectInstance = Object.Instantiate(initialEffect, transform.position, transform.rotation, transform); + return; + } + _efh_initializeEffectInstance = EffectManager.GetAndActivatePooledEffect(initialEffect, transform.position, transform.rotation); + initialEffectInstance = _efh_initializeEffectInstance.gameObject; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && NetworkServer.active && (bool)deathEffect && !spawnedEffect) + { + spawnedEffect = true; + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.origin = base.transform.position; + EffectManager.SpawnEffect(deathEffect, _effectData, transmit: true); + if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + base.OnExit(); + Debug.LogError("gwisp death onexit"); + EntityState.Destroy(base.gameObject); + if (!initialEffectInstance) + { + return; + } + if (!EffectManager.UsePools) + { + EntityState.Destroy(initialEffectInstance); + return; + } + if (_efh_initializeEffectInstance != null && _efh_initializeEffectInstance.OwningPool != null) + { + _efh_initializeEffectInstance.OwningPool.ReturnObject(_efh_initializeEffectInstance); + } + else + { + if (_efh_initializeEffectInstance != null) + { + Debug.LogFormat("GreaterWispDeathState has no owning pool {0} {1}", base.gameObject.name, base.gameObject.GetInstanceID()); + } + EntityState.Destroy(initialEffectInstance); + } + initialEffectInstance = null; + _efh_initializeEffectInstance = null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/FireCannons.cs b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/FireCannons.cs new file mode 100644 index 0000000..6a3386e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/FireCannons.cs @@ -0,0 +1,82 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.GreaterWispMonster; + +public class FireCannons : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject effectPrefab; + + public static float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + private float duration; + + private static int FireCannonsStateHash = Animator.StringToHash("FireCannons"); + + private static int FireCannonsParamHash = Animator.StringToHash("FireCannons.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + string text = "MuzzleLeft"; + string text2 = "MuzzleRight"; + duration = baseDuration / attackSpeedStat; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, text, transmit: false); + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, text2, transmit: false); + } + PlayAnimation("Gesture", FireCannonsStateHash, FireCannonsParamHash, duration); + if (!base.isAuthority || !base.modelLocator || !base.modelLocator.modelTransform) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + int childIndex = component.FindChildIndex(text); + int childIndex2 = component.FindChildIndex(text2); + Transform transform = component.FindChild(childIndex); + Transform transform2 = component.FindChild(childIndex2); + if ((bool)transform) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, transform.position, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + if ((bool)transform2) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, transform2.position, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/SpawnState.cs new file mode 100644 index 0000000..9b4a06f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GreaterWispMonster/SpawnState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GreaterWispMonster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GummyClone/GummyCloneDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.GummyClone/GummyCloneDeathState.cs new file mode 100644 index 0000000..f149601 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GummyClone/GummyCloneDeathState.cs @@ -0,0 +1,40 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.GummyClone; + +public class GummyCloneDeathState : BaseState +{ + [SerializeField] + public string soundString; + + [SerializeField] + public GameObject effectPrefab; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundString, base.gameObject); + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if (base.isAuthority && (bool)effectPrefab) + { + EffectManager.SimpleImpactEffect(effectPrefab, base.transform.position, Vector3.up, transmit: true); + } + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.GummyClone/GummyCloneSpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.GummyClone/GummyCloneSpawnState.cs new file mode 100644 index 0000000..4c75388 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.GummyClone/GummyCloneSpawnState.cs @@ -0,0 +1,88 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.GummyClone; + +public class GummyCloneSpawnState : BaseState +{ + [SerializeField] + public float duration = 4f; + + [SerializeField] + public string soundString; + + [SerializeField] + public float initialDelay; + + [SerializeField] + public GameObject effectPrefab; + + private bool hasFinished; + + private Animator modelAnimator; + + private CharacterModel characterModel; + + private CameraTargetParams.AimRequest aimRequest; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if ((bool)modelAnimator) + { + GameObject gameObject = modelAnimator.gameObject; + characterModel = gameObject.GetComponent(); + characterModel.invisibilityCount++; + } + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void OnExit() + { + base.OnExit(); + if (!hasFinished) + { + characterModel.invisibilityCount--; + } + aimRequest?.Dispose(); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, 3f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= initialDelay && !hasFinished) + { + hasFinished = true; + characterModel.invisibilityCount--; + duration = initialDelay; + if ((bool)effectPrefab) + { + EffectManager.SimpleEffect(effectPrefab, base.transform.position, Quaternion.identity, transmit: false); + } + Util.PlaySound(soundString, base.gameObject); + } + if (base.fixedAge >= duration && hasFinished && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Gup/BaseSplitDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Gup/BaseSplitDeath.cs new file mode 100644 index 0000000..e1c38b4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Gup/BaseSplitDeath.cs @@ -0,0 +1,67 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Gup; + +public class BaseSplitDeath : GenericCharacterDeath +{ + [SerializeField] + public CharacterSpawnCard characterSpawnCard; + + [SerializeField] + public int spawnCount; + + [SerializeField] + public float deathDelay; + + [SerializeField] + public float moneyMultiplier; + + public static float spawnRadiusCoefficient = 0.5f; + + public static GameObject deathEffectPrefab; + + private bool hasDied; + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!(base.fixedAge > deathDelay) || hasDied) + { + return; + } + hasDied = true; + if (NetworkServer.active) + { + EffectManager.SpawnEffect(deathEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition, + scale = base.characterBody.radius + }, transmit: true); + if ((bool)characterSpawnCard && spawnCount > 0 && (ulong)(base.healthComponent.killingDamageType & (DamageType.VoidDeath | DamageType.OutOfBounds)) == 0L) + { + BodySplitter bodySplitter = new BodySplitter(); + bodySplitter.body = base.characterBody; + bodySplitter.masterSummon.masterPrefab = characterSpawnCard.prefab; + bodySplitter.count = spawnCount; + bodySplitter.splinterInitialVelocityLocal = new Vector3(0f, 20f, 10f); + bodySplitter.minSpawnCircleRadius = base.characterBody.radius * spawnRadiusCoefficient; + bodySplitter.moneyMultiplier = moneyMultiplier; + bodySplitter.Perform(); + } + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Gup/GeepDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Gup/GeepDeath.cs new file mode 100644 index 0000000..cf9604f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Gup/GeepDeath.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Gup; + +public class GeepDeath : BaseSplitDeath +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Gup/GipDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Gup/GipDeath.cs new file mode 100644 index 0000000..d19af84 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Gup/GipDeath.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Gup; + +public class GipDeath : BaseSplitDeath +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Gup/GupDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Gup/GupDeath.cs new file mode 100644 index 0000000..b25255f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Gup/GupDeath.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Gup; + +public class GupDeath : BaseSplitDeath +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Gup/GupSpikesState.cs b/ilspy_dump/ror2_csproj/EntityStates.Gup/GupSpikesState.cs new file mode 100644 index 0000000..8aeb273 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Gup/GupSpikesState.cs @@ -0,0 +1,64 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Gup; + +public class GupSpikesState : BasicMeleeAttack +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string playbackRateParam; + + [SerializeField] + public float crossfadeDuration; + + [SerializeField] + public string initialHitboxActiveParameter; + + [SerializeField] + public string initialHitboxName; + + private HitBox initialHitBox; + + public override void OnEnter() + { + base.OnEnter(); + StartAimMode(0f); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if (!hitBoxGroup) + { + return; + } + HitBox[] hitBoxes = hitBoxGroup.hitBoxes; + foreach (HitBox hitBox in hitBoxes) + { + if (hitBox.gameObject.name == initialHitboxName) + { + initialHitBox = hitBox; + break; + } + } + } + + protected override void PlayAnimation() + { + PlayCrossfade(animationLayerName, animationStateName, playbackRateParam, duration, crossfadeDuration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)initialHitBox) + { + initialHitBox.enabled = animator.GetFloat(initialHitboxActiveParameter) > 0.5f; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Gup/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Gup/SpawnState.cs new file mode 100644 index 0000000..d2f42d9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Gup/SpawnState.cs @@ -0,0 +1,24 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Gup; + +internal class SpawnState : GenericCharacterSpawnState +{ + public static GameObject spawnEffectPrefab; + + public static string spawnEffectMuzzle; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)spawnEffectPrefab) + { + EffectManager.SpawnEffect(spawnEffectPrefab, new EffectData + { + origin = FindModelChild(spawnEffectMuzzle).position, + scale = base.characterBody.radius + }, transmit: true); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/ChargeSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/ChargeSlam.cs new file mode 100644 index 0000000..ffcc99c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/ChargeSlam.cs @@ -0,0 +1,45 @@ +using UnityEngine; + +namespace EntityStates.HAND.Weapon; + +public class ChargeSlam : BaseState +{ + public static float baseDuration = 3.5f; + + private float duration; + + private Animator modelAnimator; + + private static int ChargeSlamStateHash = Animator.StringToHash("ChargeSlam"); + + private static int ChargeSlamParamHash = Animator.StringToHash("ChargeSlam.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", ChargeSlamStateHash, ChargeSlamParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(4f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.characterMotor.isGrounded && base.isAuthority) + { + outer.SetNextState(new Slam()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/FireWinch.cs b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/FireWinch.cs new file mode 100644 index 0000000..c642a58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/FireWinch.cs @@ -0,0 +1,55 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.HAND.Weapon; + +public class FireWinch : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float duration = 2f; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "WinchHole"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration / attackSpeedStat && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/FullSwing.cs b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/FullSwing.cs new file mode 100644 index 0000000..317f5c0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/FullSwing.cs @@ -0,0 +1,139 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.HAND.Weapon; + +public class FullSwing : BaseState +{ + public static float baseDuration = 3.5f; + + public static float returnToIdlePercentage; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + public static GameObject hitEffectPrefab; + + public static GameObject swingEffectPrefab; + + private Transform hammerChildTransform; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private bool hasSwung; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Hammer"); + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + hammerChildTransform = component.FindChild("SwingCenter"); + } + } + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Gesture"); + if (modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("FullSwing3") || modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("FullSwing1")) + { + PlayCrossfade("Gesture", "FullSwing2", "FullSwing.playbackRate", duration / (1f - returnToIdlePercentage), 0.2f); + } + else if (modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("FullSwing2")) + { + PlayCrossfade("Gesture", "FullSwing3", "FullSwing.playbackRate", duration / (1f - returnToIdlePercentage), 0.2f); + } + else + { + PlayCrossfade("Gesture", "FullSwing1", "FullSwing.playbackRate", duration / (1f - returnToIdlePercentage), 0.2f); + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("Hammer.hitBoxActive") > 0.5f) + { + if (!hasSwung) + { + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, "SwingCenter", transmit: true); + hasSwung = true; + } + attack.forceVector = hammerChildTransform.right * (0f - forceMagnitude); + attack.Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private static void PullEnemies(Vector3 position, Vector3 direction, float coneAngle, float maxDistance, float force, TeamIndex excludedTeam) + { + float num = Mathf.Cos(coneAngle * 0.5f * (MathF.PI / 180f)); + Collider[] colliders; + int num2 = HGPhysics.OverlapSphere(out colliders, position, maxDistance); + for (int i = 0; i < num2; i++) + { + Collider collider = colliders[i]; + Vector3 position2 = collider.transform.position; + Vector3 normalized = (position - position2).normalized; + if (!(Vector3.Dot(-normalized, direction) >= num)) + { + continue; + } + TeamIndex teamIndex = TeamIndex.Neutral; + TeamComponent component = collider.GetComponent(); + if (!component) + { + continue; + } + teamIndex = component.teamIndex; + if (teamIndex != excludedTeam) + { + CharacterMotor component2 = collider.GetComponent(); + if ((bool)component2) + { + component2.ApplyForce(normalized * force); + } + Rigidbody component3 = collider.GetComponent(); + if ((bool)component3) + { + component3.AddForce(normalized * force, ForceMode.Impulse); + } + } + } + HGPhysics.ReturnResults(colliders); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/Slam.cs b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/Slam.cs new file mode 100644 index 0000000..cd0ed79 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HAND.Weapon/Slam.cs @@ -0,0 +1,100 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.HAND.Weapon; + +public class Slam : BaseState +{ + public static float baseDuration = 3.5f; + + public static float returnToIdlePercentage; + + public static float impactDamageCoefficient = 2f; + + public static float earthquakeDamageCoefficient = 2f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + public static GameObject hitEffectPrefab; + + public static GameObject swingEffectPrefab; + + public static GameObject projectilePrefab; + + private Transform hammerChildTransform; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private bool hasSwung; + + private static int SlamStateHash = Animator.StringToHash("Slam"); + + private static int SlamParamHash = Animator.StringToHash("Slam.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = impactDamageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Hammer"); + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + hammerChildTransform = component.FindChild("SwingCenter"); + } + } + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", SlamStateHash, SlamParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("Hammer.hitBoxActive") > 0.5f) + { + if (!hasSwung) + { + Ray aimRay = GetAimRay(); + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, "SwingCenter", transmit: true); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * earthquakeDamageCoefficient, forceMagnitude, Util.CheckRoll(critStat, base.characterBody.master)); + hasSwung = true; + } + attack.forceVector = hammerChildTransform.right; + attack.Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HAND/Overclock.cs b/ilspy_dump/ror2_csproj/EntityStates.HAND/Overclock.cs new file mode 100644 index 0000000..c26494c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HAND/Overclock.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.HAND; + +public class Overclock : BaseState +{ + public static float baseDuration = 0.25f; + + public static GameObject healEffectPrefab; + + public static float healPercentage = 0.15f; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + _ = (bool)base.characterBody; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > baseDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/ChargeTriLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/ChargeTriLaser.cs new file mode 100644 index 0000000..74c0c12 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/ChargeTriLaser.cs @@ -0,0 +1,146 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class ChargeTriLaser : BaseState +{ + public static float baseDuration = 3f; + + public static float laserMaxWidth = 0.2f; + + public static GameObject effectPrefab; + + public static GameObject laserPrefab; + + public static string attackSoundString; + + private float duration; + + private uint chargePlayID; + + private GameObject chargeEffect; + + private GameObject laserEffect; + + private LineRenderer laserLineComponent; + + private Vector3 laserDirection; + + private Vector3 visualEndPosition; + + private float flashTimer; + + private bool laserOn; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("FullBody Override", "TriLaserEnter", "TriLaser.playbackRate", duration, 0.1f); + Transform modelTransform = GetModelTransform(); + chargePlayID = Util.PlayAttackSpeedSound("Play_halcyonite_skill2_chargeup", base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleLaser"); + if ((bool)transform) + { + if ((bool)effectPrefab) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)laserPrefab) + { + laserEffect = Object.Instantiate(laserPrefab, transform.position, transform.rotation); + laserEffect.transform.parent = transform; + laserLineComponent = laserEffect.GetComponent(); + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + flashTimer = 0f; + laserOn = true; + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(chargePlayID); + base.OnExit(); + if ((bool)chargeEffect) + { + EntityState.Destroy(chargeEffect); + } + if ((bool)laserEffect) + { + EntityState.Destroy(laserEffect); + } + PlayAnimation("FullBody Override", "BufferEmpty"); + } + + public override void Update() + { + base.Update(); + if (!laserEffect || !laserLineComponent) + { + return; + } + float num = 1000f; + Ray aimRay = GetAimRay(); + Vector3 position = laserEffect.transform.parent.position; + Vector3 point = aimRay.GetPoint(num); + laserDirection = point - position; + if (Physics.Raycast(aimRay, out var hitInfo, num, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask)) + { + point = hitInfo.point; + } + laserLineComponent.SetPosition(0, position); + laserLineComponent.SetPosition(1, point); + float num2; + if (duration - base.age > 0.5f) + { + num2 = base.age / duration; + } + else + { + flashTimer -= Time.deltaTime; + if (flashTimer <= 0f) + { + laserOn = !laserOn; + flashTimer = 1f / 30f; + } + num2 = (laserOn ? 1f : 0f); + } + num2 *= laserMaxWidth; + laserLineComponent.startWidth = num2; + laserLineComponent.endWidth = num2; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + TriLaser triLaser = new TriLaser(); + triLaser.laserDirection = laserDirection; + outer.SetNextState(triLaser); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/DeathState.cs new file mode 100644 index 0000000..a5ca3d4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/DeathState.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class DeathState : GenericCharacterDeath +{ + public override void OnEnter() + { + base.OnEnter(); + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + component.FindChild("ChestGlow").transform.gameObject.GetComponent().Stop(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/GoldenSlash.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/GoldenSlash.cs new file mode 100644 index 0000000..7e4d469 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/GoldenSlash.cs @@ -0,0 +1,31 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class GoldenSlash : BasicMeleeAttack +{ + [SerializeField] + public GameObject swordPrefab; + + protected override void PlayAnimation() + { + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component && (bool)swordPrefab) + { + int childIndex = component.FindChildIndex("SwordPoint"); + EffectData effectData = new EffectData(); + effectData.origin = base.characterBody.transform.position; + effectData.rotation = Util.QuaternionSafeLookRotation(base.characterBody.transform.forward); + effectData.SetChildLocatorTransformReference(base.characterBody.transform.gameObject, childIndex); + EffectManager.SpawnEffect(swordPrefab, effectData, transmit: true); + } + PlayCrossfade("FullBody Override", "GoldenSlash", "GoldenSlash.playbackRate", duration, 0.1f); + } + + public override void OnExit() + { + PlayAnimation("FullBody Override", "BufferEmpty"); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/GoldenSwipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/GoldenSwipe.cs new file mode 100644 index 0000000..cf9f88d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/GoldenSwipe.cs @@ -0,0 +1,31 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class GoldenSwipe : BasicMeleeAttack +{ + [SerializeField] + public GameObject swordPrefab; + + protected override void PlayAnimation() + { + ChildLocator component = GetModelTransform().GetComponent(); + if ((bool)component && (bool)swordPrefab) + { + int childIndex = component.FindChildIndex("SwordPoint"); + EffectData effectData = new EffectData(); + effectData.origin = base.characterBody.transform.position; + effectData.rotation = Util.QuaternionSafeLookRotation(base.characterBody.transform.forward); + effectData.SetChildLocatorTransformReference(base.characterBody.transform.gameObject, childIndex); + EffectManager.SpawnEffect(swordPrefab, effectData, transmit: true); + } + PlayCrossfade("FullBody Override", "GoldenSwipe", "GoldenSwipe.playbackRate", duration, 0.1f); + } + + public override void OnExit() + { + PlayAnimation("FullBody Override", "BufferEmpty"); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/SpawnState.cs new file mode 100644 index 0000000..3cd73b0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/SpawnState.cs @@ -0,0 +1,50 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class SpawnState : EntityState +{ + public static float duration = 2f; + + public static float startingPrintHeight; + + public static float maxPrintHeight; + + public static float startingPrintBias; + + public static float maxPrintBias; + + public static string spawnSoundString; + + public override void OnEnter() + { + base.OnEnter(); + base.gameObject.GetComponent(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", "Spawn", "Spawn.playbackRate", duration); + PrintController printController = GetModelTransform().gameObject.AddComponent(); + printController.printTime = duration; + printController.enabled = true; + printController.startingPrintHeight = startingPrintHeight; + printController.maxPrintHeight = maxPrintHeight; + printController.startingPrintBias = startingPrintBias; + printController.maxPrintBias = maxPrintBias; + printController.disableWhenFinished = true; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/TriLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/TriLaser.cs new file mode 100644 index 0000000..92f8e10 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/TriLaser.cs @@ -0,0 +1,130 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class TriLaser : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float blastRadius; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public Vector3 laserDirection; + + private float duration; + + private Ray modifiedAimRay; + + public float fireBeamTimer = 0.5f; + + private int timesFired; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireBeamTimer += Time.deltaTime; + if (timesFired < 3 && fireBeamTimer > 0.5f) + { + FireTriLaser(); + fireBeamTimer = 0f; + timesFired++; + } + if (base.fixedAge >= duration && timesFired > 2 && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireTriLaser() + { + duration = baseDuration / attackSpeedStat; + modifiedAimRay = GetAimRay(); + modifiedAimRay.direction = laserDirection; + GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + Util.PlaySound(attackSoundString, base.gameObject); + string text = "MuzzleLaser"; + Util.PlaySound("Play_halcyonite_skill2_shoot", base.gameObject); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + PlayCrossfade("FullBody Override", "TriLaserFire", "TriLaser.playbackRate", duration * 0.5f, 0.1f); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, text, transmit: false); + } + if (!base.isAuthority) + { + return; + } + float num = 1000f; + Vector3 vector = modifiedAimRay.origin + modifiedAimRay.direction * num; + if (Physics.Raycast(modifiedAimRay, out var hitInfo, num, LayerIndex.CommonMasks.laser)) + { + vector = hitInfo.point; + } + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient; + blastAttack.baseForce = force * 0.2f; + blastAttack.position = vector; + blastAttack.radius = blastRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.SweetSpot; + blastAttack.bonusForce = force * modifiedAimRay.direction; + blastAttack.Fire(); + _ = modifiedAimRay.origin; + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + int childIndex = component.FindChildIndex(text); + if ((bool)tracerEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = vector, + start = modifiedAimRay.origin + }; + effectData.SetChildLocatorTransformReference(base.gameObject, childIndex); + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + EffectManager.SpawnEffect(hitEffectPrefab, effectData, transmit: true); + } + } + } + + public override void OnExit() + { + PlayCrossfade("FullBody Override", "TriLaserExit", "TriLaser.playbackRate", duration, 0.1f); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/WhirlwindRush.cs b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/WhirlwindRush.cs new file mode 100644 index 0000000..76c37f5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Halcyonite/WhirlwindRush.cs @@ -0,0 +1,188 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Halcyonite; + +public class WhirlwindRush : BaseState +{ + public static float chargeMovementSpeedCoefficient; + + public static float turnSpeed; + + public static float turnSmoothTime; + + public static float damageCoefficient; + + public static GameObject hitEffectPrefab; + + private Animator animator; + + private Vector3 targetMoveVector; + + private Vector3 targetMoveVectorVelocity; + + private HitBoxGroup hitboxGroup; + + private ChildLocator childLocator; + + [SerializeField] + public float spinUpDuration = 1f; + + [SerializeField] + public float duration = 2f; + + [SerializeField] + public float endSpinDuration = 1f; + + [SerializeField] + public GameObject projectilePrefab; + + private bool firedWhirlWind; + + private static int forwardSpeedParamHash = Animator.StringToHash("forwardSpeed"); + + private float originalMoveSpeed = 6.6f; + + private float originalAccSpeed = 40f; + + [SerializeField] + public float rushingMoveSpeed = 13.5f; + + [SerializeField] + public float rushingAccSpeed = 200f; + + private Vector3 safePosition; + + private float ageStartedWhirlwind; + + private float intervalToCheckForSafePath = 1f; + + public override void OnEnter() + { + originalMoveSpeed = base.characterBody.baseMoveSpeed; + originalAccSpeed = base.characterBody.baseAcceleration; + base.characterBody.baseMoveSpeed = 0.5f; + base.characterMotor.moveDirection = Vector3.zero; + safePosition = base.characterBody.corePosition; + animator = GetModelAnimator(); + childLocator = animator.GetComponent(); + PlayCrossfade("FullBody Override", "WhirlwindRushEnter", "WhirlwindRush.playbackRate", duration, 0.1f); + Util.PlaySound("Play_halcyonite_skill3_start", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + bool stopWhirlwind = base.fixedAge > duration + spinUpDuration + endSpinDuration; + if (base.fixedAge > spinUpDuration * 0.5f && !firedWhirlWind) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, base.gameObject.transform.position, Quaternion.identity, base.gameObject, base.characterBody.damage * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + firedWhirlWind = true; + Util.PlaySound("Play_halcyonite_skill3_loop", base.gameObject); + } + if (firedWhirlWind && !stopWhirlwind) + { + if (base.fixedAge - ageStartedWhirlwind > intervalToCheckForSafePath) + { + HandleIdentifySafePathForward(ref stopWhirlwind); + } + else + { + HandleProceedAlongPath(ref stopWhirlwind); + } + } + if (base.fixedAge > duration + spinUpDuration && !stopWhirlwind) + { + base.characterBody.baseMoveSpeed = 0f; + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 0f; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + } + if (stopWhirlwind) + { + base.characterBody.baseMoveSpeed = originalMoveSpeed; + base.characterBody.baseAcceleration = originalAccSpeed; + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + Util.PlaySound("Stop_halcyonite_skill3_loop", base.gameObject); + outer.SetNextStateToMain(); + } + } + + private void HandleIdentifySafePathForward(ref bool stopWhirlwind) + { + Vector3 vector = base.inputBank.aimDirection * rushingMoveSpeed * GetDeltaTime(); + vector.y = 0f; + vector += base.characterBody.aimOrigin; + Debug.DrawLine(base.characterBody.aimOrigin, base.characterBody.aimOrigin + Vector3.right, Color.grey, 10f); + Debug.DrawRay(vector + Vector3.up * 2f, Vector3.down, Color.green, 10f); + Debug.DrawLine(vector + Vector3.up * 2f, vector + Vector3.up * 2f + Vector3.up * -10f, Color.yellow, 10f); + if (!Physics.Raycast(new Ray(vector + Vector3.up * 2f, Vector3.down), out var _, 10f, (int)LayerIndex.world.mask | (int)LayerIndex.CommonMasks.characterBodiesOrDefault, QueryTriggerInteraction.Ignore)) + { + stopWhirlwind = true; + } + else + { + ageStartedWhirlwind = base.fixedAge; + } + } + + private void HandleProceedAlongPath(ref bool stopWhirlwind) + { + if (!base.characterMotor.isGrounded) + { + TeleportHelper.TeleportBody(base.characterBody, safePosition); + stopWhirlwind = true; + } + else + { + safePosition = base.characterBody.footPosition; + } + targetMoveVector = Vector3.ProjectOnPlane(Vector3.SmoothDamp(targetMoveVector, base.inputBank.aimDirection, ref targetMoveVectorVelocity, turnSmoothTime, turnSpeed), Vector3.up).normalized; + base.characterDirection.moveVector = targetMoveVector; + Vector3 forward = base.characterDirection.forward; + float value = moveSpeedStat * chargeMovementSpeedCoefficient; + base.characterMotor.moveDirection = forward * chargeMovementSpeedCoefficient; + animator.SetFloat(forwardSpeedParamHash, value); + base.characterBody.baseMoveSpeed = rushingMoveSpeed; + base.characterBody.baseAcceleration = rushingAccSpeed; + } + + public override void OnExit() + { + base.characterMotor.moveDirection = Vector3.zero; + PlayCrossfade("FullBody Override", "WhirlwindRushExit", "WhirlwindRush.playbackRate", duration, 0.1f); + Util.PlaySound("Play_halcyonite_skill3_end", base.gameObject); + Util.PlaySound("Stop_halcyonite_skill3_loop", base.gameObject); + base.characterBody.RecalculateStats(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Headstompers/BaseHeadstompersState.cs b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/BaseHeadstompersState.cs new file mode 100644 index 0000000..ba755dc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/BaseHeadstompersState.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates.Headstompers; + +public class BaseHeadstompersState : EntityState +{ + private static readonly List instancesList = new List(); + + protected NetworkedBodyAttachment networkedBodyAttachment; + + protected GameObject bodyGameObject; + + protected CharacterBody body; + + protected CharacterMotor bodyMotor; + + protected InputBankTest bodyInputBank; + + protected bool jumpButtonDown + { + get + { + if ((bool)bodyInputBank) + { + return bodyInputBank.jump.down; + } + return false; + } + } + + protected bool slamButtonDown + { + get + { + if ((bool)bodyInputBank) + { + return bodyInputBank.interact.down; + } + return false; + } + } + + protected bool isGrounded + { + get + { + if ((bool)bodyMotor) + { + return bodyMotor.isGrounded; + } + return false; + } + } + + public static BaseHeadstompersState FindForBody(CharacterBody body) + { + for (int i = 0; i < instancesList.Count; i++) + { + if ((object)instancesList[i].body == body) + { + return instancesList[i]; + } + } + return null; + } + + public override void OnEnter() + { + base.OnEnter(); + instancesList.Add(this); + networkedBodyAttachment = GetComponent(); + if ((bool)networkedBodyAttachment) + { + bodyGameObject = networkedBodyAttachment.attachedBodyObject; + body = networkedBodyAttachment.attachedBody; + if ((bool)bodyGameObject) + { + bodyMotor = bodyGameObject.GetComponent(); + bodyInputBank = bodyGameObject.GetComponent(); + } + } + } + + public override void OnExit() + { + instancesList.Remove(this); + base.OnExit(); + } + + protected bool ReturnToIdleIfGroundedAuthority() + { + if ((bool)bodyMotor && bodyMotor.isGrounded) + { + outer.SetNextState(new HeadstompersIdle()); + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersCharge.cs b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersCharge.cs new file mode 100644 index 0000000..73d7ef5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersCharge.cs @@ -0,0 +1,49 @@ +using UnityEngine; + +namespace EntityStates.Headstompers; + +public class HeadstompersCharge : BaseHeadstompersState +{ + private float inputStopwatch; + + public static float maxChargeDuration = 0.5f; + + public static float minVelocityY = 1f; + + public static float accelerationY = 10f; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + FixedUpdateAuthority(); + } + } + + private void FixedUpdateAuthority() + { + if (ReturnToIdleIfGroundedAuthority()) + { + return; + } + inputStopwatch = (base.slamButtonDown ? (inputStopwatch + Time.deltaTime) : 0f); + if (inputStopwatch >= maxChargeDuration) + { + outer.SetNextState(new HeadstompersFall()); + } + else if (!base.slamButtonDown) + { + outer.SetNextState(new HeadstompersIdle()); + } + else if ((bool)bodyMotor) + { + Vector3 velocity = bodyMotor.velocity; + if (velocity.y < minVelocityY) + { + velocity.y = Mathf.MoveTowards(velocity.y, minVelocityY, accelerationY * Time.deltaTime); + bodyMotor.velocity = velocity; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersCooldown.cs b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersCooldown.cs new file mode 100644 index 0000000..810f4fe --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersCooldown.cs @@ -0,0 +1,42 @@ +using RoR2; + +namespace EntityStates.Headstompers; + +public class HeadstompersCooldown : BaseHeadstompersState +{ + public static float baseDuration = 10f; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + if ((bool)body) + { + Inventory inventory = body.inventory; + int num = ((!inventory) ? 1 : inventory.GetItemCount(RoR2Content.Items.FallBoots)); + if (num > 0) + { + duration /= num; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + FixedUpdateAuthority(); + } + } + + private void FixedUpdateAuthority() + { + if (base.fixedAge >= duration) + { + outer.SetNextState(new HeadstompersIdle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersFall.cs b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersFall.cs new file mode 100644 index 0000000..50cbab7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersFall.cs @@ -0,0 +1,200 @@ +using System; +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.Headstompers; + +public class HeadstompersFall : BaseHeadstompersState +{ + private float stopwatch; + + public static float maxFallDuration = 0f; + + public static float maxFallSpeed = 30f; + + public static float maxDistance = 30f; + + public static float initialFallSpeed = 10f; + + public static float accelerationY = 40f; + + public static float minimumRadius = 5f; + + public static float maximumRadius = 100f; + + public static float minimumDamageCoefficient = 10f; + + public static float maximumDamageCoefficient = 100f; + + public static float seekCone = 20f; + + public static float springboardSpeed = 30f; + + private Transform seekTransform; + + private bool seekLost; + + private CharacterMotor onHitGroundProvider; + + private float initialY; + + public override void OnEnter() + { + base.OnEnter(); + if (!base.isAuthority) + { + return; + } + if ((bool)body) + { + TeamMask allButNeutral = TeamMask.allButNeutral; + TeamIndex objectTeam = TeamComponent.GetObjectTeam(bodyGameObject); + if (objectTeam != TeamIndex.None) + { + allButNeutral.RemoveTeam(objectTeam); + } + BullseyeSearch obj = new BullseyeSearch + { + filterByLoS = true, + maxDistanceFilter = 300f, + maxAngleFilter = seekCone, + searchOrigin = body.footPosition, + searchDirection = Vector3.down, + sortMode = BullseyeSearch.SortMode.Angle, + teamMaskFilter = allButNeutral, + viewer = body + }; + initialY = body.footPosition.y; + obj.RefreshCandidates(); + seekTransform = obj.GetResults().FirstOrDefault()?.transform; + } + SetOnHitGroundProviderAuthority(bodyMotor); + if ((bool)bodyMotor) + { + bodyMotor.velocity.y = Mathf.Min(bodyMotor.velocity.y, 0f - initialFallSpeed); + } + } + + private void SetOnHitGroundProviderAuthority(CharacterMotor newOnHitGroundProvider) + { + if ((object)onHitGroundProvider != null) + { + onHitGroundProvider.onHitGroundAuthority -= OnMotorHitGroundAuthority; + } + onHitGroundProvider = newOnHitGroundProvider; + if ((object)onHitGroundProvider != null) + { + onHitGroundProvider.onHitGroundAuthority += OnMotorHitGroundAuthority; + } + } + + public override void OnExit() + { + SetOnHitGroundProviderAuthority(null); + base.OnExit(); + } + + private void OnMotorHitGroundAuthority(ref CharacterMotor.HitGroundInfo hitGroundInfo) + { + DoStompExplosionAuthority(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + FixedUpdateAuthority(); + } + } + + private void FixedUpdateAuthority() + { + stopwatch += Time.deltaTime; + if (base.isGrounded) + { + DoStompExplosionAuthority(); + } + else if (stopwatch >= maxFallDuration) + { + outer.SetNextState(new HeadstompersCooldown()); + } + else + { + if (!bodyMotor) + { + return; + } + Vector3 velocity = bodyMotor.velocity; + if (velocity.y > 0f - maxFallSpeed) + { + velocity.y = Mathf.MoveTowards(velocity.y, 0f - maxFallSpeed, accelerationY * Time.deltaTime); + } + if ((bool)seekTransform && !seekLost) + { + Vector3 normalized = (seekTransform.position - body.footPosition).normalized; + if (Vector3.Dot(Vector3.down, normalized) >= Mathf.Cos(seekCone * (MathF.PI / 180f))) + { + if (velocity.y < 0f) + { + Vector3 vector = normalized * (0f - velocity.y); + vector.y = 0f; + Vector3 vector2 = velocity; + vector2.y = 0f; + vector2 = vector; + velocity.x = vector2.x; + velocity.z = vector2.z; + } + } + else + { + seekLost = true; + } + } + bodyMotor.velocity = velocity; + } + } + + private void DoStompExplosionAuthority() + { + if ((bool)body) + { + Inventory inventory = body.inventory; + if (((!inventory || inventory.GetItemCount(RoR2Content.Items.FallBoots) != 0) ? 1 : 0) > (false ? 1 : 0)) + { + bodyMotor.velocity = Vector3.zero; + float num = Mathf.Max(0f, initialY - body.footPosition.y); + if (num > 0f) + { + float t = Mathf.InverseLerp(0f, maxDistance, num); + float num2 = Mathf.Lerp(minimumDamageCoefficient, maximumDamageCoefficient, t); + float num3 = Mathf.Lerp(minimumRadius, maximumRadius, t); + BlastAttack obj = new BlastAttack + { + attacker = body.gameObject, + inflictor = body.gameObject + }; + obj.teamIndex = TeamComponent.GetObjectTeam(obj.attacker); + obj.position = body.footPosition; + obj.procCoefficient = 1f; + obj.radius = num3; + obj.baseForce = 200f * num2; + obj.bonusForce = Vector3.up * 2000f; + obj.baseDamage = body.damage * num2; + obj.falloffModel = BlastAttack.FalloffModel.SweetSpot; + obj.crit = Util.CheckRoll(body.crit, body.master); + obj.damageColorIndex = DamageColorIndex.Item; + obj.attackerFiltering = AttackerFiltering.NeverHitSelf; + obj.Fire(); + EffectData effectData = new EffectData(); + effectData.origin = body.footPosition; + effectData.scale = num3; + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/BootShockwave"), effectData, transmit: true); + } + } + } + SetOnHitGroundProviderAuthority(null); + outer.SetNextState(new HeadstompersCooldown()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersIdle.cs b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersIdle.cs new file mode 100644 index 0000000..e683d61 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Headstompers/HeadstompersIdle.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Headstompers; + +public class HeadstompersIdle : BaseHeadstompersState +{ + private float inputStopwatch; + + public static float inputConfirmationDelay = 0.1f; + + private bool jumpBoostOk; + + public static GameObject jumpEffect; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + FixedUpdateAuthority(); + } + } + + private void FixedUpdateAuthority() + { + inputStopwatch = (base.slamButtonDown ? (inputStopwatch + GetDeltaTime()) : 0f); + if (base.isGrounded) + { + jumpBoostOk = true; + } + else if (jumpBoostOk && base.jumpButtonDown && (bool)bodyMotor) + { + Vector3 velocity = bodyMotor.velocity; + if (velocity.y > 0f) + { + velocity.y *= 2f; + bodyMotor.velocity = velocity; + jumpBoostOk = false; + } + EffectManager.SimpleImpactEffect(jumpEffect, bodyGameObject.transform.position, Vector3.up, transmit: true); + } + if (inputStopwatch >= inputConfirmationDelay && !base.isGrounded) + { + outer.SetNextState(new HeadstompersCharge()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Heretic.Weapon/Squawk.cs b/ilspy_dump/ror2_csproj/EntityStates.Heretic.Weapon/Squawk.cs new file mode 100644 index 0000000..26e197b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Heretic.Weapon/Squawk.cs @@ -0,0 +1,22 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Heretic.Weapon; + +public class Squawk : EntityState +{ + [SerializeField] + public string soundName; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundName, base.gameObject); + outer.SetNextStateToMain(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Heretic/SpawnOnNewStageState.cs b/ilspy_dump/ror2_csproj/EntityStates.Heretic/SpawnOnNewStageState.cs new file mode 100644 index 0000000..dc0fdb4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Heretic/SpawnOnNewStageState.cs @@ -0,0 +1,10 @@ +namespace EntityStates.Heretic; + +public class SpawnOnNewStageState : SpawnState +{ + public override void OnEnter() + { + base.OnEnter(); + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Heretic/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Heretic/SpawnState.cs new file mode 100644 index 0000000..e9b97fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Heretic/SpawnState.cs @@ -0,0 +1,58 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Heretic; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject effectPrefab; + + public static Material overlayMaterial; + + public static float overlayDuration; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + EffectManager.SimpleEffect(effectPrefab, base.characterBody.corePosition, Quaternion.identity, transmit: false); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + CharacterModel component = modelTransform.GetComponent(); + if ((bool)component && (bool)overlayMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(component.gameObject); + temporaryOverlayInstance.duration = overlayDuration; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = overlayMaterial; + temporaryOverlayInstance.inspectorCharacterModel = component; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/BurrowIn.cs b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/BurrowIn.cs new file mode 100644 index 0000000..d62446d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/BurrowIn.cs @@ -0,0 +1,53 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.HermitCrab; + +public class BurrowIn : BaseState +{ + public static GameObject burrowPrefab; + + public static float baseDuration; + + public static string burrowInSoundString; + + private float stopwatch; + + private float duration; + + private Transform modelTransform; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "BurrowIn", "BurrowIn.playbackRate", duration, 0.1f); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + Util.PlaySound(burrowInSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + Burrowed nextState = new Burrowed(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/BurrowOut.cs b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/BurrowOut.cs new file mode 100644 index 0000000..301a896 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/BurrowOut.cs @@ -0,0 +1,52 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.HermitCrab; + +public class BurrowOut : BaseState +{ + public static GameObject burrowPrefab; + + public static float baseDuration; + + public static string burrowOutSoundString; + + private float stopwatch; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "BurrowOut", "BurrowOut.playbackRate", duration, 0.1f); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + Util.PlaySound(burrowOutSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/Burrowed.cs b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/Burrowed.cs new file mode 100644 index 0000000..69e33fd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/Burrowed.cs @@ -0,0 +1,35 @@ +namespace EntityStates.HermitCrab; + +public class Burrowed : BaseState +{ + public static float mortarCooldown; + + public float duration; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "Burrowed", 0.1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (base.inputBank.moveVector.sqrMagnitude > 0.1f) + { + outer.SetNextState(new BurrowOut()); + } + if (base.fixedAge >= duration && base.inputBank.skill1.down) + { + outer.SetNextState(new FireMortar()); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/FireMortar.cs b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/FireMortar.cs new file mode 100644 index 0000000..6e20795 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/FireMortar.cs @@ -0,0 +1,116 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.HermitCrab; + +public class FireMortar : BaseState +{ + public static GameObject mortarProjectilePrefab; + + public static GameObject mortarMuzzleflashEffect; + + public static int mortarCount; + + public static string mortarMuzzleName; + + public static string mortarSoundString; + + public static float mortarDamageCoefficient; + + public static float baseDuration; + + public static float timeToTarget = 3f; + + public static float projectileVelocity = 55f; + + public static float minimumDistance; + + private float stopwatch; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Gesture, Additive", "FireMortar", 0f); + Util.PlaySound(mortarSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(mortarMuzzleflashEffect, base.gameObject, mortarMuzzleName, transmit: false); + if (base.isAuthority) + { + Fire(); + } + } + + private void Fire() + { + Ray aimRay = GetAimRay(); + Ray ray = new Ray(aimRay.origin, Vector3.up); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + bool flag = false; + Vector3 vector = Vector3.zero; + RaycastHit hitInfo; + if ((bool)hurtBox) + { + vector = hurtBox.transform.position; + flag = true; + } + else if (Physics.Raycast(aimRay, out hitInfo, 1000f, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + vector = hitInfo.point; + flag = true; + } + float magnitude = projectileVelocity; + if (flag) + { + Vector3 vector2 = vector - ray.origin; + Vector2 vector3 = new Vector2(vector2.x, vector2.z); + float magnitude2 = vector3.magnitude; + Vector2 vector4 = vector3 / magnitude2; + if (magnitude2 < minimumDistance) + { + magnitude2 = minimumDistance; + } + float y = Trajectory.CalculateInitialYSpeed(timeToTarget, vector2.y); + float num = magnitude2 / timeToTarget; + Vector3 direction = new Vector3(vector4.x * num, y, vector4.y * num); + magnitude = direction.magnitude; + ray.direction = direction; + } + for (int i = 0; i < mortarCount; i++) + { + Quaternion rotation = Util.QuaternionSafeLookRotation(ray.direction + ((i != 0) ? (Random.insideUnitSphere * 0.05f) : Vector3.zero)); + ProjectileManager.instance.FireProjectile(mortarProjectilePrefab, ray.origin, rotation, base.gameObject, damageStat * mortarDamageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, magnitude); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch > duration) + { + Burrowed burrowed = new Burrowed(); + burrowed.duration = Burrowed.mortarCooldown; + outer.SetNextState(burrowed); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/SpawnState.cs new file mode 100644 index 0000000..2b82f86 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.HermitCrab/SpawnState.cs @@ -0,0 +1,42 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.HermitCrab; + +public class SpawnState : BaseState +{ + private float stopwatch; + + public static GameObject burrowPrefab; + + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/ChargeArrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/ChargeArrow.cs new file mode 100644 index 0000000..8ad5c69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/ChargeArrow.cs @@ -0,0 +1,186 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class ChargeArrow : BaseState +{ + public static float baseTotalDuration; + + public static float baseMaxChargeTime; + + public static int maxCharges; + + public static GameObject chargeEffectPrefab; + + public static GameObject muzzleflashEffectPrefab; + + public static string chargeStockSoundString; + + public static string chargeLoopStartSoundString; + + public static string chargeLoopStopSoundString; + + public static float minBonusBloom; + + public static float maxBonusBloom; + + public static float minArrowDamageCoefficient; + + public static float maxArrowDamageCoefficient; + + public static float orbDamageCoefficient; + + public static float orbRange; + + public static float orbFrequency; + + public static float orbProcCoefficient; + + private float stopwatch; + + private GameObject chargeLeftInstance; + + private GameObject chargeRightInstance; + + private Animator animator; + + private int charge; + + private int lastCharge; + + private ChildLocator childLocator; + + private float totalDuration; + + private float maxChargeTime; + + private bool cachedSprinting; + + private float originalMinYaw; + + private float originalMaxYaw; + + private string muzzleString; + + private static int chargingArrowParamHash = Animator.StringToHash("chargingArrow"); + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + private static int FireSeekingArrowStateHash = Animator.StringToHash("FireSeekingArrow"); + + public override void OnEnter() + { + base.OnEnter(); + totalDuration = baseTotalDuration / attackSpeedStat; + maxChargeTime = baseMaxChargeTime / attackSpeedStat; + muzzleString = "Muzzle"; + Transform modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + animator = GetModelAnimator(); + cachedSprinting = base.characterBody.isSprinting; + if (!cachedSprinting) + { + animator.SetBool(chargingArrowParamHash, value: true); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(maxChargeTime + 1f); + } + } + + public override void OnExit() + { + base.OnExit(); + animator.SetBool(chargingArrowParamHash, value: false); + if (!cachedSprinting) + { + PlayAnimation("Gesture, Override", BufferEmptyStateHash); + PlayAnimation("Gesture, Additive", BufferEmptyStateHash); + } + } + + private void FireOrbArrow() + { + if (NetworkServer.active) + { + HuntressArrowOrb huntressArrowOrb = new HuntressArrowOrb(); + huntressArrowOrb.damageValue = base.characterBody.damage * orbDamageCoefficient; + huntressArrowOrb.isCrit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + huntressArrowOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + huntressArrowOrb.attacker = base.gameObject; + huntressArrowOrb.damageColorIndex = DamageColorIndex.Poison; + huntressArrowOrb.procChainMask.AddProc(ProcType.HealOnHit); + huntressArrowOrb.procCoefficient = orbProcCoefficient; + Ray aimRay = GetAimRay(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.maxDistanceFilter = orbRange; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(huntressArrowOrb.teamIndex); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.RefreshCandidates(); + List list = bullseyeSearch.GetResults().ToList(); + HurtBox hurtBox = ((list.Count > 0) ? list[Random.Range(0, list.Count)] : null); + if ((bool)hurtBox) + { + Transform transform = childLocator.FindChild(muzzleString).transform; + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + huntressArrowOrb.origin = transform.position; + huntressArrowOrb.target = hurtBox; + PlayAnimation("Gesture, Override", FireSeekingArrowStateHash); + PlayAnimation("Gesture, Additive", FireSeekingArrowStateHash); + OrbManager.instance.AddOrb(huntressArrowOrb); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (cachedSprinting != base.characterBody.isSprinting && base.isAuthority) + { + outer.SetNextStateToMain(); + } + else if (!cachedSprinting) + { + lastCharge = charge; + stopwatch += GetDeltaTime(); + charge = Mathf.Min((int)(stopwatch / maxChargeTime * (float)maxCharges), maxCharges); + float damageCoefficient = Mathf.Lerp(minArrowDamageCoefficient, maxArrowDamageCoefficient, charge); + if (lastCharge < charge && charge == maxCharges) + { + EffectManager.SimpleMuzzleFlash(chargeEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if ((stopwatch >= totalDuration || !base.inputBank || !base.inputBank.skill1.down) && base.isAuthority) + { + FireArrow fireArrow = new FireArrow(); + fireArrow.damageCoefficient = damageCoefficient; + outer.SetNextState(fireArrow); + } + } + else + { + stopwatch += GetDeltaTime(); + if (stopwatch >= 1f / orbFrequency / attackSpeedStat) + { + stopwatch -= 1f / orbFrequency / attackSpeedStat; + FireOrbArrow(); + } + if ((!base.inputBank || !base.inputBank.skill1.down) && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireArrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireArrow.cs new file mode 100644 index 0000000..93eecef --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireArrow.cs @@ -0,0 +1,131 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class FireArrow : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject projectilePrefab; + + public static int arrowCountMax = 1; + + public float damageCoefficient; + + public static float fireDuration = 1f; + + public static float baseDuration = 2f; + + public static float arcAngle = 5f; + + public static float recoilAmplitude = 1f; + + public static string attackSoundString; + + public static float spreadBloomValue = 0.3f; + + public static float smallHopStrength; + + private Ray aimRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private static int fireArrowHash = Animator.StringToHash("FireArrow"); + + private static int fireArrowParamHash = Animator.StringToHash("FireArrow.playbackRate"); + + private void FireGrenade(string targetMuzzle) + { + Util.PlaySound(attackSoundString, base.gameObject); + aimRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + aimRay.origin = transform.position; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + float x = Random.Range(0f, base.characterBody.spreadBloomAngle); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, aimRay.direction); + Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y = vector.y; + vector.y = 0f; + float angle = Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f + arcAngle; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * aimRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + if ((bool)base.characterMotor && smallHopStrength != 0f) + { + base.characterMotor.velocity.y = smallHopStrength; + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + fireTimer -= GetDeltaTime(); + float num = fireDuration / attackSpeedStat / (float)arrowCountMax; + if (fireTimer <= 0f && grenadeCount < arrowCountMax) + { + PlayAnimation("Gesture, Additive", fireArrowHash, fireArrowParamHash, duration - num); + PlayAnimation("Gesture, Override", fireArrowHash, fireArrowParamHash, duration - num); + FireGrenade("Muzzle"); + fireTimer += num; + grenadeCount++; + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireArrowOld.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireArrowOld.cs new file mode 100644 index 0000000..230153c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireArrowOld.cs @@ -0,0 +1,65 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class FireArrowOld : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "Muzzle"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Gesture"); + modelAnimator.SetFloat("FireArrow.playbackRate", attackSpeedStat); + modelAnimator.PlayInFixedTime("FireArrow", layerIndex, 0f); + muzzleName = "MuzzleRight"; + modelAnimator.Update(0f); + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireFlurrySeekingArrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireFlurrySeekingArrow.cs new file mode 100644 index 0000000..f78230f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireFlurrySeekingArrow.cs @@ -0,0 +1,29 @@ +using RoR2.Orbs; +using UnityEngine; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class FireFlurrySeekingArrow : FireSeekingArrow +{ + public static GameObject critMuzzleflashEffectPrefab; + + public static int critMaxArrowCount; + + public static float critBaseArrowReloadDuration; + + public override void OnEnter() + { + base.OnEnter(); + if (isCrit) + { + muzzleflashEffectPrefab = critMuzzleflashEffectPrefab; + maxArrowCount = critMaxArrowCount; + arrowReloadDuration = critBaseArrowReloadDuration / attackSpeedStat; + } + } + + protected override GenericDamageOrb CreateArrowOrb() + { + return new HuntressFlurryArrowOrb(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireGlaive.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireGlaive.cs new file mode 100644 index 0000000..82b7f40 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireGlaive.cs @@ -0,0 +1,69 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class FireGlaive : BaseState +{ + public static GameObject projectilePrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + private float duration; + + private static int FireGlaiveStateHash = Animator.StringToHash("FireGlaive"); + + private static int FireGlaiveParamHash = Animator.StringToHash("FireGlaive.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + Transform modelTransform = GetModelTransform(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture", FireGlaiveStateHash, FireGlaiveParamHash, duration); + Vector3 position = aimRay.origin; + Quaternion rotation = Util.QuaternionSafeLookRotation(aimRay.direction); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("RightHand"); + if ((bool)transform) + { + position = transform.position; + } + } + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, position, rotation, base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireSeekingArrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireSeekingArrow.cs new file mode 100644 index 0000000..6a4965b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/FireSeekingArrow.cs @@ -0,0 +1,145 @@ +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class FireSeekingArrow : BaseState +{ + [SerializeField] + public float orbDamageCoefficient; + + [SerializeField] + public float orbProcCoefficient; + + [SerializeField] + public string muzzleString; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public int maxArrowCount; + + [SerializeField] + public float baseArrowReloadDuration; + + private float duration; + + protected float arrowReloadDuration; + + private float arrowReloadTimer; + + protected bool isCrit; + + private int firedArrowCount; + + private HurtBox initialOrbTarget; + + private ChildLocator childLocator; + + private HuntressTracker huntressTracker; + + private Animator animator; + + private static int fireSeekingShotStateHash = Animator.StringToHash("FireSeekingShot"); + + private static int fireSeekingShotParamHash = Animator.StringToHash("FireSeekingShot.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + huntressTracker = GetComponent(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + animator = modelTransform.GetComponent(); + } + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + if ((bool)huntressTracker && base.isAuthority) + { + initialOrbTarget = huntressTracker.GetTrackingTarget(); + } + duration = baseDuration / attackSpeedStat; + arrowReloadDuration = baseArrowReloadDuration / attackSpeedStat; + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration + 1f); + } + PlayCrossfade("Gesture, Override", fireSeekingShotStateHash, fireSeekingShotParamHash, duration, duration * 0.2f / attackSpeedStat); + PlayCrossfade("Gesture, Additive", fireSeekingShotStateHash, fireSeekingShotParamHash, duration, duration * 0.2f / attackSpeedStat); + isCrit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + } + + public override void OnExit() + { + base.OnExit(); + FireOrbArrow(); + } + + protected virtual GenericDamageOrb CreateArrowOrb() + { + return new HuntressArrowOrb(); + } + + private void FireOrbArrow() + { + if (firedArrowCount < maxArrowCount && !(arrowReloadTimer > 0f) && NetworkServer.active) + { + firedArrowCount++; + arrowReloadTimer = arrowReloadDuration; + GenericDamageOrb genericDamageOrb = CreateArrowOrb(); + genericDamageOrb.damageValue = base.characterBody.damage * orbDamageCoefficient; + genericDamageOrb.isCrit = isCrit; + genericDamageOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + genericDamageOrb.attacker = base.gameObject; + genericDamageOrb.procCoefficient = orbProcCoefficient; + HurtBox hurtBox = initialOrbTarget; + if ((bool)hurtBox) + { + Transform transform = childLocator.FindChild(muzzleString); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + genericDamageOrb.origin = transform.position; + genericDamageOrb.target = hurtBox; + OrbManager.instance.AddOrb(genericDamageOrb); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + arrowReloadTimer -= GetDeltaTime(); + if (animator.GetFloat("FireSeekingShot.fire") > 0f) + { + FireOrbArrow(); + } + if (base.fixedAge > duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + writer.Write(HurtBoxReference.FromHurtBox(initialOrbTarget)); + } + + public override void OnDeserialize(NetworkReader reader) + { + initialOrbTarget = reader.ReadHurtBoxReference().ResolveHurtBox(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/IdleTracking.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/IdleTracking.cs new file mode 100644 index 0000000..5d61faa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/IdleTracking.cs @@ -0,0 +1,178 @@ +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class IdleTracking : BaseState +{ + public static float maxTrackingDistance = 20f; + + public static float maxTrackingAngle = 20f; + + public static float orbDamageCoefficient; + + public static float orbProcCoefficient; + + public static string muzzleString; + + public static GameObject muzzleflashEffectPrefab; + + public static string attackSoundString; + + public static float fireFrequency; + + private float fireTimer; + + private Transform trackingIndicatorTransform; + + private HurtBox trackingTarget; + + private ChildLocator childLocator; + + private BullseyeSearch search; + + private GameObject TrackingIndicatorPrefab; + + private EffectManagerHelper _emh_trackingIndicator; + + private static int FireSeekingArrowStateHash = Animator.StringToHash("FireSeekingArrow"); + + public override void Reset() + { + base.Reset(); + fireTimer = 0f; + trackingIndicatorTransform = null; + trackingTarget = null; + childLocator = null; + if (search != null) + { + search.Reset(); + } + _emh_trackingIndicator = null; + } + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + } + } + + protected void DestroyTrackingIndicator() + { + if ((bool)trackingIndicatorTransform) + { + if (_emh_trackingIndicator != null && _emh_trackingIndicator.OwningPool != null) + { + _emh_trackingIndicator.OwningPool.ReturnObject(_emh_trackingIndicator); + } + else + { + EntityState.Destroy(trackingIndicatorTransform.gameObject); + } + trackingIndicatorTransform = null; + _emh_trackingIndicator = null; + } + } + + public override void OnExit() + { + DestroyTrackingIndicator(); + base.OnExit(); + } + + private void FireOrbArrow() + { + if (NetworkServer.active) + { + HuntressArrowOrb huntressArrowOrb = new HuntressArrowOrb(); + huntressArrowOrb.damageValue = base.characterBody.damage * orbDamageCoefficient; + huntressArrowOrb.isCrit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + huntressArrowOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + huntressArrowOrb.attacker = base.gameObject; + huntressArrowOrb.damageColorIndex = DamageColorIndex.Poison; + huntressArrowOrb.procChainMask.AddProc(ProcType.HealOnHit); + huntressArrowOrb.procCoefficient = orbProcCoefficient; + HurtBox hurtBox = trackingTarget; + if ((bool)hurtBox) + { + Transform transform = childLocator.FindChild(muzzleString).transform; + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + huntressArrowOrb.origin = transform.position; + huntressArrowOrb.target = hurtBox; + PlayAnimation("Gesture, Override", FireSeekingArrowStateHash); + PlayAnimation("Gesture, Additive", FireSeekingArrowStateHash); + Util.PlaySound(attackSoundString, base.gameObject); + OrbManager.instance.AddOrb(huntressArrowOrb); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + fireTimer -= GetDeltaTime(); + if ((bool)base.characterBody) + { + float extraRaycastDistance = 0f; + Ray ray = CameraRigController.ModifyAimRayIfApplicable(GetAimRay(), base.gameObject, out extraRaycastDistance); + if (search == null) + { + search = new BullseyeSearch(); + } + search.searchOrigin = ray.origin; + search.searchDirection = ray.direction; + search.maxDistanceFilter = maxTrackingDistance + extraRaycastDistance; + search.maxAngleFilter = maxTrackingAngle; + search.teamMaskFilter = TeamMask.allButNeutral; + search.teamMaskFilter.RemoveTeam(TeamComponent.GetObjectTeam(base.gameObject)); + search.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + search.RefreshCandidates(); + trackingTarget = search.GetResults().FirstOrDefault(); + } + if ((bool)trackingTarget) + { + if (!trackingIndicatorTransform) + { + if (TrackingIndicatorPrefab == null) + { + TrackingIndicatorPrefab = LegacyResourcesAPI.Load("Prefabs/ShieldTransferIndicator"); + } + if (!EffectManager.ShouldUsePooledEffect(TrackingIndicatorPrefab)) + { + trackingIndicatorTransform = Object.Instantiate(TrackingIndicatorPrefab, trackingTarget.transform.position, Quaternion.identity).transform; + } + else + { + _emh_trackingIndicator = EffectManager.GetAndActivatePooledEffect(TrackingIndicatorPrefab, trackingTarget.transform.position, Quaternion.identity); + trackingIndicatorTransform = _emh_trackingIndicator.gameObject.transform; + } + } + trackingIndicatorTransform.position = trackingTarget.transform.position; + if ((bool)base.inputBank && base.inputBank.skill1.down && fireTimer <= 0f) + { + fireTimer = 1f / fireFrequency / attackSpeedStat; + FireOrbArrow(); + } + } + else + { + DestroyTrackingIndicator(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/ThrowGlaive.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/ThrowGlaive.cs new file mode 100644 index 0000000..cf01157 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.HuntressWeapon/ThrowGlaive.cs @@ -0,0 +1,219 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Huntress.HuntressWeapon; + +public class ThrowGlaive : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargePrefab; + + public static GameObject muzzleFlashPrefab; + + public static float smallHopStrength; + + public static float antigravityStrength; + + public static float damageCoefficient = 1.2f; + + public static float damageCoefficientPerBounce = 1.1f; + + public static float glaiveProcCoefficient; + + public static int maxBounceCount; + + public static float glaiveTravelSpeed; + + public static float glaiveBounceRange; + + public static string attackSoundString; + + private float duration; + + private float stopwatch; + + private Animator animator; + + private GameObject chargeEffect; + + private Transform modelTransform; + + private HuntressTracker huntressTracker; + + private ChildLocator childLocator; + + private bool hasTriedToThrowGlaive; + + private bool hasSuccessfullyThrownGlaive; + + private HurtBox initialOrbTarget; + + private EffectManagerHelper _emh_chargeEffect; + + private static int ThrowGlaiveStateHash = Animator.StringToHash("ThrowGlaive"); + + private static int ThrowGlaiveParamHash = Animator.StringToHash("ThrowGlaive.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + stopwatch = 0f; + animator = null; + chargeEffect = null; + modelTransform = null; + huntressTracker = null; + childLocator = null; + hasTriedToThrowGlaive = false; + hasSuccessfullyThrownGlaive = false; + initialOrbTarget = null; + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + animator = GetModelAnimator(); + huntressTracker = GetComponent(); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + if ((bool)huntressTracker && base.isAuthority) + { + initialOrbTarget = huntressTracker.GetTrackingTarget(); + } + if ((bool)base.characterMotor && smallHopStrength != 0f) + { + base.characterMotor.velocity.y = smallHopStrength; + } + PlayAnimation("FullBody, Override", ThrowGlaiveStateHash, ThrowGlaiveParamHash, duration); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild("HandR"); + if ((bool)transform && (bool)chargePrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargePrefab)) + { + chargeEffect = Object.Instantiate(chargePrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(chargePrefab, transform.position, transform.rotation); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.parent = transform; + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + protected void DestroyChargeEffect() + { + if ((bool)chargeEffect) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + chargeEffect = null; + _emh_chargeEffect = null; + } + } + + public override void OnExit() + { + base.OnExit(); + DestroyChargeEffect(); + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 1.5f); + animator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + if (!hasTriedToThrowGlaive) + { + FireOrbGlaive(); + } + if (!hasSuccessfullyThrownGlaive && NetworkServer.active) + { + base.skillLocator.secondary.AddOneStock(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (!hasTriedToThrowGlaive && animator.GetFloat("ThrowGlaive.fire") > 0f) + { + DestroyChargeEffect(); + FireOrbGlaive(); + } + base.characterMotor.velocity.y += antigravityStrength * GetDeltaTime() * (1f - stopwatch / duration); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireOrbGlaive() + { + if (NetworkServer.active && !hasTriedToThrowGlaive) + { + hasTriedToThrowGlaive = true; + LightningOrb lightningOrb = new LightningOrb(); + lightningOrb.lightningType = LightningOrb.LightningType.HuntressGlaive; + lightningOrb.damageValue = base.characterBody.damage * damageCoefficient; + lightningOrb.isCrit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + lightningOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + lightningOrb.attacker = base.gameObject; + lightningOrb.procCoefficient = glaiveProcCoefficient; + lightningOrb.bouncesRemaining = maxBounceCount; + lightningOrb.speed = glaiveTravelSpeed; + lightningOrb.bouncedObjects = new List(); + lightningOrb.range = glaiveBounceRange; + lightningOrb.damageCoefficientPerBounce = damageCoefficientPerBounce; + HurtBox hurtBox = initialOrbTarget; + if ((bool)hurtBox) + { + hasSuccessfullyThrownGlaive = true; + Transform transform = childLocator.FindChild("HandR"); + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, "HandR", transmit: true); + lightningOrb.origin = transform.position; + lightningOrb.target = hurtBox; + OrbManager.instance.AddOrb(lightningOrb); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnSerialize(NetworkWriter writer) + { + writer.Write(HurtBoxReference.FromHurtBox(initialOrbTarget)); + } + + public override void OnDeserialize(NetworkReader reader) + { + initialOrbTarget = reader.ReadHurtBoxReference().ResolveHurtBox(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress.Weapon/FireArrowSnipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress.Weapon/FireArrowSnipe.cs new file mode 100644 index 0000000..b1db9bd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress.Weapon/FireArrowSnipe.cs @@ -0,0 +1,31 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Huntress.Weapon; + +public class FireArrowSnipe : GenericBulletBaseState +{ + public float charge; + + public static float recoilAmplitude; + + private static int FireArrowSnipeStateHash = Animator.StringToHash("FireArrowSnipe"); + + private static int FireArrowSnipeParamHash = Animator.StringToHash("FireArrowSnipe.playbackRate"); + + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + _ = (bool)(base.skillLocator ? base.skillLocator.primary : null); + } + + protected override void FireBullet(Ray aimRay) + { + base.FireBullet(aimRay); + base.characterBody.SetSpreadBloom(0.2f, canOnlyIncreaseBloom: false); + AddRecoil(-0.6f * recoilAmplitude, -0.8f * recoilAmplitude, -0.1f * recoilAmplitude, 0.1f * recoilAmplitude); + PlayAnimation("Body", FireArrowSnipeStateHash, FireArrowSnipeParamHash, duration); + base.healthComponent.TakeDamageForce(aimRay.direction * -400f, alwaysApply: true); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/AimArrowSnipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/AimArrowSnipe.cs new file mode 100644 index 0000000..602843b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/AimArrowSnipe.cs @@ -0,0 +1,70 @@ +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Huntress; + +public class AimArrowSnipe : BaseArrowBarrage +{ + public static SkillDef primarySkillDef; + + public static GameObject crosshairOverridePrefab; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private GenericSkill primarySkillSlot; + + private AimAnimator modelAimAnimator; + + public override void OnEnter() + { + base.OnEnter(); + modelAimAnimator = GetModelTransform().GetComponent(); + if ((bool)modelAimAnimator) + { + modelAimAnimator.enabled = true; + } + primarySkillSlot = (base.skillLocator ? base.skillLocator.primary : null); + if ((bool)primarySkillSlot) + { + primarySkillSlot.SetSkillOverride(this, primarySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + PlayCrossfade("Body", "ArrowBarrageLoop", 0.1f); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + } + + protected override void HandlePrimaryAttack() + { + if ((bool)primarySkillSlot) + { + primarySkillSlot.ExecuteIfReady(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + if (!primarySkillSlot || primarySkillSlot.stock == 0) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)primarySkillSlot) + { + primarySkillSlot.UnsetSkillOverride(this, primarySkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/ArrowRain.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/ArrowRain.cs new file mode 100644 index 0000000..169a87a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/ArrowRain.cs @@ -0,0 +1,118 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Huntress; + +public class ArrowRain : BaseArrowBarrage +{ + public static float arrowRainRadius = 0f; + + public static float damageCoefficient; + + public static GameObject projectilePrefab; + + public static GameObject areaIndicatorPrefab; + + public static GameObject muzzleFlashEffect; + + private GameObject areaIndicatorInstance; + + private bool shouldFireArrowRain; + + private EffectManagerHelper _emh_areaIndicatorInstance; + + private Vector3 _cachedAreaIndicatorScale = Vector3.one; + + private static int LoopArrowRainStateHash = Animator.StringToHash("LoopArrowRain"); + + public override void Reset() + { + base.Reset(); + areaIndicatorInstance = null; + shouldFireArrowRain = false; + _emh_areaIndicatorInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("FullBody, Override", LoopArrowRainStateHash); + if ((bool)areaIndicatorPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(areaIndicatorPrefab)) + { + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab); + } + else + { + _emh_areaIndicatorInstance = EffectManager.GetAndActivatePooledEffect(areaIndicatorPrefab, Vector3.zero, Quaternion.identity); + areaIndicatorInstance = _emh_areaIndicatorInstance.gameObject; + } + if (areaIndicatorInstance != null) + { + _cachedAreaIndicatorScale.x = arrowRainRadius; + _cachedAreaIndicatorScale.y = arrowRainRadius; + _cachedAreaIndicatorScale.z = arrowRainRadius; + areaIndicatorInstance.transform.localScale = _cachedAreaIndicatorScale; + } + } + } + + private void UpdateAreaIndicator() + { + if ((bool)areaIndicatorInstance) + { + float maxDistance = 1000f; + if (Physics.Raycast(GetAimRay(), out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + areaIndicatorInstance.transform.position = hitInfo.point; + areaIndicatorInstance.transform.up = hitInfo.normal; + } + } + } + + public override void Update() + { + base.Update(); + UpdateAreaIndicator(); + } + + protected override void HandlePrimaryAttack() + { + base.HandlePrimaryAttack(); + shouldFireArrowRain = true; + outer.SetNextStateToMain(); + } + + protected void DoFireArrowRain() + { + EffectManager.SimpleMuzzleFlash(muzzleFlashEffect, base.gameObject, "Muzzle", transmit: false); + if ((bool)areaIndicatorInstance && shouldFireArrowRain) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, areaIndicatorInstance.transform.position, areaIndicatorInstance.transform.rotation, base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + if (shouldFireArrowRain && !outer.destroying) + { + DoFireArrowRain(); + } + if ((bool)areaIndicatorInstance) + { + if (_emh_areaIndicatorInstance != null && _emh_areaIndicatorInstance.OwningPool != null) + { + _emh_areaIndicatorInstance.OwningPool.ReturnObject(_emh_areaIndicatorInstance); + } + else + { + EntityState.Destroy(areaIndicatorInstance.gameObject); + } + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/BackflipState.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BackflipState.cs new file mode 100644 index 0000000..fdde995 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BackflipState.cs @@ -0,0 +1,159 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Huntress; + +public class BackflipState : BaseState +{ + public static float duration = 0.9f; + + public static float initialSpeedCoefficient; + + public static float finalSpeedCoefficient; + + public static string dodgeSoundString; + + public static float dodgeFOV; + + public static float orbDamageCoefficient; + + public static float orbRange; + + public static int orbCountMax; + + public static float orbPrefireDuration; + + public static float orbFrequency; + + public static float orbProcCoefficient; + + public static string muzzleString; + + public static float smallHopStrength; + + public static GameObject muzzleflashEffectPrefab; + + private ChildLocator childLocator; + + private float stopwatch; + + private float orbStopwatch; + + private Vector3 forwardDirection; + + private Animator animator; + + private int orbCount; + + private static int BackflipStateHash = Animator.StringToHash("Backflip"); + + private static int BackflipParamHash = Animator.StringToHash("Backflip.playbackRate"); + + private static int FireSeekingArrowStateHash = Animator.StringToHash("FireSeekingArrow"); + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + base.characterMotor.velocity.y = Mathf.Max(base.characterMotor.velocity.y, 0f); + animator = GetModelAnimator(); + Util.PlaySound(dodgeSoundString, base.gameObject); + orbStopwatch = 0f - orbPrefireDuration; + if ((bool)base.characterMotor && smallHopStrength != 0f) + { + base.characterMotor.velocity.y = smallHopStrength; + } + if (base.isAuthority && (bool)base.inputBank) + { + forwardDirection = -Vector3.ProjectOnPlane(base.inputBank.aimDirection, Vector3.up); + } + base.characterDirection.moveVector = -forwardDirection; + PlayAnimation("FullBody, Override", BackflipStateHash, BackflipParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + orbStopwatch += deltaTime; + if ((bool)base.cameraTargetParams) + { + base.cameraTargetParams.fovOverride = Mathf.Lerp(dodgeFOV, 60f, stopwatch / duration); + } + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + Vector3 velocity = base.characterMotor.velocity; + Vector3 velocity2 = forwardDirection * (moveSpeedStat * Mathf.Lerp(initialSpeedCoefficient, finalSpeedCoefficient, stopwatch / duration)); + base.characterMotor.velocity = velocity2; + base.characterMotor.velocity.y = velocity.y; + base.characterMotor.moveDirection = forwardDirection; + } + if (orbStopwatch >= 1f / orbFrequency / attackSpeedStat && orbCount < orbCountMax) + { + orbStopwatch -= 1f / orbFrequency / attackSpeedStat; + FireOrbArrow(); + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireOrbArrow() + { + if (NetworkServer.active) + { + orbCount++; + HuntressArrowOrb huntressArrowOrb = new HuntressArrowOrb(); + huntressArrowOrb.damageValue = base.characterBody.damage * orbDamageCoefficient; + huntressArrowOrb.isCrit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + huntressArrowOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + huntressArrowOrb.attacker = base.gameObject; + huntressArrowOrb.damageColorIndex = DamageColorIndex.Poison; + huntressArrowOrb.procChainMask.AddProc(ProcType.HealOnHit); + huntressArrowOrb.procCoefficient = orbProcCoefficient; + Ray aimRay = GetAimRay(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.maxDistanceFilter = orbRange; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(huntressArrowOrb.teamIndex); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.RefreshCandidates(); + List list = bullseyeSearch.GetResults().ToList(); + HurtBox hurtBox = ((list.Count > 0) ? list[Random.Range(0, list.Count)] : null); + if ((bool)hurtBox) + { + Transform transform = childLocator.FindChild(muzzleString).transform; + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + huntressArrowOrb.origin = transform.position; + huntressArrowOrb.target = hurtBox; + PlayAnimation("Gesture, Override", FireSeekingArrowStateHash); + PlayAnimation("Gesture, Additive", FireSeekingArrowStateHash); + OrbManager.instance.AddOrb(huntressArrowOrb); + } + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)base.cameraTargetParams) + { + base.cameraTargetParams.fovOverride = -1f; + } + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 1.5f); + animator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/BaseArrowBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BaseArrowBarrage.cs new file mode 100644 index 0000000..59874ac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BaseArrowBarrage.cs @@ -0,0 +1,77 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Huntress; + +public class BaseArrowBarrage : BaseState +{ + [SerializeField] + public float maxDuration; + + [SerializeField] + public string beginLoopSoundString; + + [SerializeField] + public string endLoopSoundString; + + [SerializeField] + public string fireSoundString; + + private HuntressTracker huntressTracker; + + private CameraTargetParams.AimRequest aimRequest; + + private static int FireArrowRainStateHash = Animator.StringToHash("FireArrowRain"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginLoopSoundString, base.gameObject); + huntressTracker = GetComponent(); + if ((bool)huntressTracker) + { + huntressTracker.enabled = false; + } + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = Vector3.zero; + } + if (base.isAuthority && (bool)base.inputBank) + { + if ((bool)base.skillLocator && base.skillLocator.utility.IsReady() && base.inputBank.skill3.justPressed) + { + outer.SetNextStateToMain(); + } + else if (base.fixedAge >= maxDuration || base.inputBank.skill1.justPressed || base.inputBank.skill4.justPressed) + { + HandlePrimaryAttack(); + } + } + } + + protected virtual void HandlePrimaryAttack() + { + } + + public override void OnExit() + { + PlayAnimation("FullBody, Override", FireArrowRainStateHash); + Util.PlaySound(endLoopSoundString, base.gameObject); + Util.PlaySound(fireSoundString, base.gameObject); + aimRequest?.Dispose(); + if ((bool)huntressTracker) + { + huntressTracker.enabled = true; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/BaseBeginArrowBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BaseBeginArrowBarrage.cs new file mode 100644 index 0000000..0503cbd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BaseBeginArrowBarrage.cs @@ -0,0 +1,146 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Huntress; + +public class BaseBeginArrowBarrage : BaseState +{ + private Transform modelTransform; + + [SerializeField] + public float basePrepDuration; + + [SerializeField] + public float blinkDuration = 0.3f; + + [SerializeField] + public float jumpCoefficient = 25f; + + public static GameObject blinkPrefab; + + public static string blinkSoundString; + + [SerializeField] + public Vector3 blinkVector; + + private Vector3 worldBlinkVector; + + private float prepDuration; + + private bool beginBlink; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + protected CameraTargetParams.AimRequest aimRequest; + + private static int BeginArrowRainStateHash = Animator.StringToHash("BeginArrowRain"); + + private static int BeginArrowRainParamHash = Animator.StringToHash("BeginArrowRain.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(blinkSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + } + prepDuration = basePrepDuration / attackSpeedStat; + PlayAnimation("FullBody, Override", BeginArrowRainStateHash, BeginArrowRainParamHash, prepDuration); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = Vector3.zero; + } + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + Vector3 direction = GetAimRay().direction; + direction.y = 0f; + direction.Normalize(); + Vector3 up = Vector3.up; + worldBlinkVector = Matrix4x4.TRS(base.transform.position, Util.QuaternionSafeLookRotation(direction, up), new Vector3(1f, 1f, 1f)).MultiplyPoint3x4(blinkVector) - base.transform.position; + worldBlinkVector.Normalize(); + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(worldBlinkVector); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= prepDuration && !beginBlink) + { + beginBlink = true; + CreateBlinkEffect(base.transform.position); + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + } + if (beginBlink && (bool)base.characterMotor) + { + base.characterMotor.velocity = Vector3.zero; + base.characterMotor.rootMotion += worldBlinkVector * (base.characterBody.jumpPower * jumpCoefficient * GetDeltaTime()); + } + if (base.fixedAge >= blinkDuration + prepDuration && base.isAuthority) + { + outer.SetNextState(InstantiateNextState()); + } + } + + protected virtual EntityState InstantiateNextState() + { + return null; + } + + public override void OnExit() + { + CreateBlinkEffect(base.transform.position); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 0.6f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashBright"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + TemporaryOverlayInstance temporaryOverlayInstance2 = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance2.duration = 0.7f; + temporaryOverlayInstance2.animateShaderAlpha = true; + temporaryOverlayInstance2.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance2.destroyComponentOnEnd = true; + temporaryOverlayInstance2.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashExpanded"); + temporaryOverlayInstance2.AddToCharacterModel(modelTransform.GetComponent()); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + aimRequest?.Dispose(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/BeginArrowRain.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BeginArrowRain.cs new file mode 100644 index 0000000..65a87eb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BeginArrowRain.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Huntress; + +public class BeginArrowRain : BaseBeginArrowBarrage +{ + protected override EntityState InstantiateNextState() + { + return new ArrowRain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/BeginArrowSnipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BeginArrowSnipe.cs new file mode 100644 index 0000000..e9af21d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BeginArrowSnipe.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Huntress; + +public class BeginArrowSnipe : BaseBeginArrowBarrage +{ + protected override EntityState InstantiateNextState() + { + return new AimArrowSnipe(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/BlinkState.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BlinkState.cs new file mode 100644 index 0000000..30cfcc1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/BlinkState.cs @@ -0,0 +1,125 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Huntress; + +public class BlinkState : BaseState +{ + private Transform modelTransform; + + public static GameObject blinkPrefab; + + private float stopwatch; + + private Vector3 blinkVector = Vector3.zero; + + [SerializeField] + public float duration = 0.3f; + + [SerializeField] + public float speedCoefficient = 25f; + + [SerializeField] + public string beginSoundString; + + [SerializeField] + public string endSoundString; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + blinkVector = GetBlinkVector(); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + } + + protected virtual Vector3 GetBlinkVector() + { + return base.inputBank.aimDirection; + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(blinkVector); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.velocity = Vector3.zero; + base.characterMotor.rootMotion += blinkVector * (moveSpeedStat * speedCoefficient * GetDeltaTime()); + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + Util.PlaySound(endSoundString, base.gameObject); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 0.6f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashBright"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + TemporaryOverlayInstance temporaryOverlayInstance2 = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance2.duration = 0.7f; + temporaryOverlayInstance2.animateShaderAlpha = true; + temporaryOverlayInstance2.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance2.destroyComponentOnEnd = true; + temporaryOverlayInstance2.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashExpanded"); + temporaryOverlayInstance2.AddToCharacterModel(modelTransform.GetComponent()); + } + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.disableAirControlUntilCollision = false; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Huntress/MiniBlinkState.cs b/ilspy_dump/ror2_csproj/EntityStates.Huntress/MiniBlinkState.cs new file mode 100644 index 0000000..731a311 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Huntress/MiniBlinkState.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace EntityStates.Huntress; + +public class MiniBlinkState : BlinkState +{ + protected override Vector3 GetBlinkVector() + { + return ((base.inputBank.moveVector == Vector3.zero) ? base.characterDirection.forward : base.inputBank.moveVector).normalized; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/BlinkState.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/BlinkState.cs new file mode 100644 index 0000000..9175534 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/BlinkState.cs @@ -0,0 +1,326 @@ +using System.Linq; +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.ImpBossMonster; + +public class BlinkState : BaseState +{ + private Transform modelTransform; + + [SerializeField] + public bool disappearWhileBlinking; + + [SerializeField] + public GameObject blinkPrefab; + + [SerializeField] + public GameObject blinkDestinationPrefab; + + [SerializeField] + public Material destealthMaterial; + + private Vector3 blinkDestination = Vector3.zero; + + private Vector3 blinkStart = Vector3.zero; + + [SerializeField] + public float duration = 0.3f; + + [SerializeField] + public float exitDuration; + + [SerializeField] + public float destinationAlertDuration; + + [SerializeField] + public float blinkDistance = 25f; + + [SerializeField] + public string beginSoundString; + + [SerializeField] + public string endSoundString; + + [SerializeField] + public float blastAttackRadius; + + [SerializeField] + public float blastAttackDamageCoefficient; + + [SerializeField] + public float blastAttackForce; + + [SerializeField] + public float blastAttackProcCoefficient; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private ChildLocator childLocator; + + private GameObject blinkDestinationInstance; + + private bool isExiting; + + private bool hasBlinked; + + private BullseyeSearch search; + + private BlastAttack attack; + + private EffectData _effectData; + + private EffectManagerHelper _emh_blinkDestinationInstance; + + private int originalLayer; + + private static int BlinkEndStateHash = Animator.StringToHash("BlinkEnd"); + + private static int BlinkEndParamHash = Animator.StringToHash("BlinkEnd.playbackRate"); + + public override void Reset() + { + base.Reset(); + modelTransform = null; + blinkDestination = Vector3.zero; + blinkStart = Vector3.zero; + animator = null; + characterModel = null; + hurtboxGroup = null; + childLocator = null; + blinkDestinationInstance = null; + isExiting = false; + hasBlinked = false; + if (search != null) + { + search.Reset(); + } + if (attack != null) + { + attack.Reset(); + } + if (_effectData != null) + { + _effectData.Reset(); + } + _emh_blinkDestinationInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + childLocator = modelTransform.GetComponent(); + } + if (disappearWhileBlinking) + { + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)childLocator) + { + childLocator.FindChild("DustCenter").gameObject.SetActive(value: false); + } + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + CalculateBlinkDestination(); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + } + + private void CalculateBlinkDestination() + { + Vector3 vector = Vector3.zero; + Ray aimRay = GetAimRay(); + if (search == null) + { + search = new BullseyeSearch(); + } + search.searchOrigin = aimRay.origin; + search.searchDirection = aimRay.direction; + search.maxDistanceFilter = blinkDistance; + search.teamMaskFilter = TeamMask.allButNeutral; + search.filterByLoS = false; + search.teamMaskFilter.RemoveTeam(TeamComponent.GetObjectTeam(base.gameObject)); + search.sortMode = BullseyeSearch.SortMode.Angle; + search.RefreshCandidates(); + HurtBox hurtBox = search.GetResults().FirstOrDefault(); + if ((bool)hurtBox) + { + vector = hurtBox.transform.position - base.transform.position; + } + blinkDestination = base.transform.position; + blinkStart = base.transform.position; + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNode(base.transform.position + vector, base.characterBody.hullClassification); + groundNodes.GetNodePosition(nodeIndex, out blinkDestination); + blinkDestination += base.transform.position - base.characterBody.footPosition; + base.characterDirection.forward = vector; + } + + private void CreateBlinkEffect(Vector3 origin) + { + if ((bool)blinkPrefab) + { + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.rotation = Util.QuaternionSafeLookRotation(blinkDestination - blinkStart); + _effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, _effectData, transmit: false); + } + } + + private void SetPosition(Vector3 newPosition) + { + if ((bool)base.characterMotor) + { + base.characterMotor.Motor.SetPositionAndRotation(newPosition, Quaternion.identity); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = Vector3.zero; + } + if (!hasBlinked) + { + SetPosition(Vector3.Lerp(blinkStart, blinkDestination, base.fixedAge / duration)); + } + if (base.fixedAge >= duration - destinationAlertDuration && !hasBlinked) + { + hasBlinked = true; + if ((bool)blinkDestinationPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(blinkDestinationPrefab)) + { + blinkDestinationInstance = Object.Instantiate(blinkDestinationPrefab, blinkDestination, Quaternion.identity); + } + else + { + _emh_blinkDestinationInstance = EffectManager.GetAndActivatePooledEffect(blinkDestinationPrefab, blinkDestination, Quaternion.identity); + blinkDestinationInstance = _emh_blinkDestinationInstance.gameObject; + } + blinkDestinationInstance.GetComponent().newDuration = destinationAlertDuration; + } + SetPosition(blinkDestination); + } + if (base.fixedAge >= duration) + { + ExitCleanup(); + } + if (base.fixedAge >= duration + exitDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void ExitCleanup() + { + if (isExiting) + { + return; + } + isExiting = true; + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + Util.PlaySound(endSoundString, base.gameObject); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + modelTransform = GetModelTransform(); + if (blastAttackDamageCoefficient > 0f) + { + if (attack == null) + { + attack = new BlastAttack(); + } + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * blastAttackDamageCoefficient; + attack.baseForce = blastAttackForce; + attack.position = blinkDestination; + attack.radius = blastAttackRadius; + attack.falloffModel = BlastAttack.FalloffModel.Linear; + attack.attackerFiltering = AttackerFiltering.NeverHitSelf; + attack.Fire(); + } + if (disappearWhileBlinking) + { + if ((bool)modelTransform && (bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(animator.gameObject); + temporaryOverlayInstance.duration = 1f; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = animator.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)childLocator) + { + childLocator.FindChild("DustCenter").gameObject.SetActive(value: true); + } + PlayAnimation("Gesture, Additive", BlinkEndStateHash, BlinkEndParamHash, exitDuration); + } + if ((bool)blinkDestinationInstance) + { + if (_emh_blinkDestinationInstance != null && _emh_blinkDestinationInstance.OwningPool != null) + { + _emh_blinkDestinationInstance.OwningPool.ReturnObject(_emh_blinkDestinationInstance); + } + else + { + EntityState.Destroy(blinkDestinationInstance); + } + _emh_blinkDestinationInstance = null; + blinkDestinationInstance = null; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = true; + } + } + + public override void OnExit() + { + base.OnExit(); + ExitCleanup(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/DeathState.cs new file mode 100644 index 0000000..1e1ca86 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/DeathState.cs @@ -0,0 +1,128 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ImpBossMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialEffect; + + public static GameObject deathEffect; + + private static float duration = 3.3166666f; + + private float stopwatch; + + private Animator animator; + + private bool hasPlayedDeathEffect; + + private bool attemptedDeathBehavior; + + private EffectManagerHelper _emh_initialEffect; + + private MaterialPropertyBlock block; + + private static int DeathStateHash = Animator.StringToHash("Death"); + + private static int DeathEffectParamHash = Animator.StringToHash("DeathEffect"); + + public override void Reset() + { + base.Reset(); + stopwatch = 0f; + animator = null; + hasPlayedDeathEffect = false; + attemptedDeathBehavior = false; + _emh_initialEffect = null; + if (block == null) + { + block = new MaterialPropertyBlock(); + } + } + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + if ((bool)base.modelLocator) + { + Transform modelTransform = base.modelLocator.modelTransform; + ChildLocator component = modelTransform.GetComponent(); + CharacterModel component2 = modelTransform.GetComponent(); + if ((bool)component) + { + component.FindChild("DustCenter").gameObject.SetActive(value: false); + if ((bool)initialEffect) + { + EffectManager.SimpleMuzzleFlash(initialEffect, base.gameObject, "DeathCenter", transmit: false); + if (EffectManager.ShouldUsePooledEffect(initialEffect)) + { + _emh_initialEffect = EffectManager.LastSpawnedEffect; + } + } + } + if ((bool)component2) + { + for (int i = 0; i < component2.baseRendererInfos.Length; i++) + { + component2.baseRendererInfos[i].ignoreOverlays = true; + } + } + } + PlayAnimation("Fullbody Override", DeathStateHash); + } + + public override void FixedUpdate() + { + if ((bool)animator) + { + stopwatch += GetDeltaTime(); + if (!hasPlayedDeathEffect && animator.GetFloat(DeathEffectParamHash) > 0.5f) + { + hasPlayedDeathEffect = true; + EffectManager.SimpleMuzzleFlash(deathEffect, base.gameObject, "DeathCenter", transmit: false); + } + if (stopwatch >= duration) + { + AttemptDeathBehavior(); + } + } + } + + private void AttemptDeathBehavior() + { + if (attemptedDeathBehavior) + { + return; + } + attemptedDeathBehavior = true; + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if (NetworkServer.active) + { + if (_emh_initialEffect != null && _emh_initialEffect.OwningPool != null) + { + _emh_initialEffect.OwningPool.ReturnObject(_emh_initialEffect); + _emh_initialEffect = null; + } + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + AttemptDeathBehavior(); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/FireVoidspikes.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/FireVoidspikes.cs new file mode 100644 index 0000000..30d1579 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/FireVoidspikes.cs @@ -0,0 +1,169 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ImpBossMonster; + +public class FireVoidspikes : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float procCoefficient; + + public static float selfForce; + + public static float forceMagnitude = 16f; + + public static GameObject hitEffectPrefab; + + public static GameObject swipeEffectPrefab; + + public static string enterSoundString; + + public static string attackSoundString; + + public static float walkSpeedPenaltyCoefficient; + + public static int projectileCount; + + public static float projectileYawSpread; + + public static float projectileDamageCoefficient; + + public static float projectileSpeed; + + public static float projectileSpeedPerProjectile; + + public static GameObject projectilePrefab; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private int slashCount; + + private Transform modelTransform; + + private int chosenAnim = -1; + + private static int FireVoidspikesLStateHash = Animator.StringToHash("FireVoidspikesL"); + + private static int FireVoidspikesRStateHash = Animator.StringToHash("FireVoidspikesR"); + + private static int FireVoidspikesParamHash = Animator.StringToHash("FireVoidspikes.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedPenaltyCoefficient; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = GetTeam(); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + attack.procCoefficient = procCoefficient; + attack.damageType = DamageType.BleedOnHit; + Util.PlaySound(enterSoundString, base.gameObject); + if (base.isAuthority) + { + chosenAnim = ((!Util.CheckRoll(50f)) ? 1 : 0); + } + if ((bool)modelAnimator) + { + int animationStateHash = ((chosenAnim == 1) ? FireVoidspikesLStateHash : FireVoidspikesRStateHash); + PlayAnimation("Gesture, Additive", animationStateHash, FireVoidspikesParamHash, duration); + PlayAnimation("Gesture, Override", animationStateHash, FireVoidspikesParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration + 3f); + } + } + + public override void OnExit() + { + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && slashCount <= 0) + { + if (modelAnimator.GetFloat("HandR.hitBoxActive") > 0.1f) + { + FireSpikeFan(GetAimRay(), "FireVoidspikesR", "HandR"); + } + if (modelAnimator.GetFloat("HandL.hitBoxActive") > 0.1f) + { + FireSpikeFan(GetAimRay(), "FireVoidspikesL", "HandL"); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireSpikeFan(Ray aimRay, string muzzleName, string hitBoxGroupName) + { + Util.PlaySound(attackSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(swipeEffectPrefab, base.gameObject, muzzleName, transmit: false); + slashCount++; + if (base.isAuthority) + { + Vector3 forward = base.characterDirection.forward; + if ((bool)modelTransform) + { + attack.hitBoxGroup = FindHitBoxGroup(hitBoxGroupName); + attack.forceVector = forward * forceMagnitude; + attack.Fire(); + } + if ((bool)base.characterMotor) + { + base.characterMotor.ApplyForce(forward * selfForce, alwaysApply: true); + } + for (int i = 0; i < projectileCount; i++) + { + FireSpikeAuthority(aimRay, 0f, ((float)projectileCount / 2f - (float)i) * projectileYawSpread, projectileSpeed + projectileSpeedPerProjectile * (float)i); + } + } + } + + private void FireSpikeAuthority(Ray aimRay, float bonusPitch, float bonusYaw, float speed) + { + Vector3 forward = Util.ApplySpread(aimRay.direction, 0f, 0f, 1f, 1f, bonusYaw, bonusPitch); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * projectileDamageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, speed); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((char)chosenAnim); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + chosenAnim = reader.ReadChar(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/GroundPound.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/GroundPound.cs new file mode 100644 index 0000000..dff33f3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/GroundPound.cs @@ -0,0 +1,115 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ImpBossMonster; + +public class GroundPound : BaseState +{ + private float stopwatch; + + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float blastAttackRadius; + + private BlastAttack attack; + + public static string initialAttackSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject slamEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject swipeEffectPrefab; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + private float duration; + + private ChildLocator childLocator; + + private int attackCount; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + Util.PlaySound(initialAttackSoundString, base.gameObject); + attack = new BlastAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * damageCoefficient; + attack.baseForce = forceMagnitude; + attack.radius = blastAttackRadius; + attack.falloffModel = BlastAttack.FalloffModel.SweetSpot; + attack.attackerFiltering = AttackerFiltering.NeverHitSelf; + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Fullbody Override", "GroundPound", "GroundPound.playbackRate", duration, 0.2f); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration + 3f); + } + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if ((bool)modelAnimator) + { + if (modelAnimator.GetFloat("GroundPound.hitBoxActive") > 0.5f) + { + if (!hasAttacked) + { + if (NetworkServer.active) + { + attack.position = childLocator.FindChild("GroundPoundCenter").transform.position; + attack.Fire(); + } + if (base.isAuthority) + { + EffectManager.SimpleMuzzleFlash(slamEffectPrefab, base.gameObject, "GroundPoundCenter", transmit: true); + } + EffectManager.SimpleMuzzleFlash(swipeEffectPrefab, base.gameObject, (attackCount % 2 == 0) ? "FireVoidspikesL" : "FireVoidspikesR", transmit: true); + attackCount++; + hasAttacked = true; + } + } + else + { + hasAttacked = false; + } + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/SpawnState.cs new file mode 100644 index 0000000..2e87201 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpBossMonster/SpawnState.cs @@ -0,0 +1,60 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ImpBossMonster; + +public class SpawnState : BaseState +{ + private float stopwatch; + + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + public static Material destealthMaterial; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Animator modelAnimator = GetModelAnimator(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectData effectData = new EffectData(); + effectData.origin = base.transform.position; + EffectManager.SpawnEffect(spawnEffectPrefab, effectData, transmit: false); + } + if ((bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelAnimator.gameObject); + temporaryOverlayInstance.duration = 1f; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = modelAnimator.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster.Weapon/CloakPermanent.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster.Weapon/CloakPermanent.cs new file mode 100644 index 0000000..86a6c7c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster.Weapon/CloakPermanent.cs @@ -0,0 +1,30 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.ImpMonster.Weapon; + +public class CloakPermanent : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Cloak); + } + } + + public override void OnExit() + { + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Cloak); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/Backstab.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/Backstab.cs new file mode 100644 index 0000000..aa4cb9f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/Backstab.cs @@ -0,0 +1,84 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ImpMonster; + +public class Backstab : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + public static GameObject hitEffectPrefab; + + public static GameObject biteEffectPrefab; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private bool hasBit; + + private static int BackstabStateHash = Animator.StringToHash("Backstab"); + + private static int BackstabParamHash = Animator.StringToHash("Backstab.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Backstab"); + } + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", BackstabStateHash, BackstabParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("Bite.hitBoxActive") > 0.1f) + { + if (!hasBit) + { + EffectManager.SimpleMuzzleFlash(biteEffectPrefab, base.gameObject, "MuzzleMouth", transmit: true); + hasBit = true; + } + attack.forceVector = base.transform.forward * forceMagnitude; + attack.Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/BlinkState.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/BlinkState.cs new file mode 100644 index 0000000..3466251 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/BlinkState.cs @@ -0,0 +1,140 @@ +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.ImpMonster; + +public class BlinkState : BaseState +{ + private Transform modelTransform; + + public static GameObject blinkPrefab; + + public static Material destealthMaterial; + + private float stopwatch; + + private Vector3 blinkDestination = Vector3.zero; + + private Vector3 blinkStart = Vector3.zero; + + public static float duration = 0.3f; + + public static float blinkDistance = 25f; + + public static string beginSoundString; + + public static string endSoundString; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private static int BlinkEndStateHash = Animator.StringToHash("BlinkEnd"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + Vector3 vector = base.inputBank.moveVector * blinkDistance; + blinkDestination = base.transform.position; + blinkStart = base.transform.position; + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNode(base.transform.position + vector, base.characterBody.hullClassification); + groundNodes.GetNodePosition(nodeIndex, out blinkDestination); + blinkDestination += base.transform.position - base.characterBody.footPosition; + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(blinkDestination - blinkStart); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: false); + } + + private void SetPosition(Vector3 newPosition) + { + if ((bool)base.characterMotor) + { + base.characterMotor.Motor.SetPositionAndRotation(newPosition, Quaternion.identity); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.velocity = Vector3.zero; + } + SetPosition(Vector3.Lerp(blinkStart, blinkDestination, stopwatch / duration)); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + Util.PlaySound(endSoundString, base.gameObject); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + modelTransform = GetModelTransform(); + if ((bool)modelTransform && (bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(animator.gameObject); + temporaryOverlayInstance.duration = 1f; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = animator.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = true; + } + PlayAnimation("Gesture, Additive", BlinkEndStateHash); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/ChargeSpines.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/ChargeSpines.cs new file mode 100644 index 0000000..e81e08d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/ChargeSpines.cs @@ -0,0 +1,96 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ImpMonster; + +public class ChargeSpines : BaseState +{ + public static float baseDuration = 1f; + + public static GameObject effectPrefab; + + private float duration; + + private GameObject chargeEffect; + + private EffectManagerHelper _emh_chargeEffect; + + private static int ChargeSpinesStateHash = Animator.StringToHash("ChargeSpines"); + + private static int ChargeSpinesParamHash = Animator.StringToHash("ChargeSpines.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffect = null; + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleMouth"); + if ((bool)transform && (bool)effectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.parent = transform; + } + } + } + PlayAnimation("Gesture", ChargeSpinesStateHash, ChargeSpinesParamHash, duration); + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeEffect) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + _emh_chargeEffect = null; + chargeEffect = null; + } + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireSpines nextState = new FireSpines(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/DeathState.cs new file mode 100644 index 0000000..75d8ab3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/DeathState.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ImpMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialEffect; + + public static GameObject deathEffect; + + private static float duration = 1.333f; + + private float stopwatch; + + private Animator animator; + + private bool hasPlayedDeathEffect; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + if ((bool)base.modelLocator && (bool)base.modelLocator.modelTransform.GetComponent() && (bool)initialEffect) + { + EffectManager.SimpleMuzzleFlash(initialEffect, base.gameObject, "Base", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)animator) + { + stopwatch += GetDeltaTime(); + if (!hasPlayedDeathEffect && animator.GetFloat("DeathEffect") > 0.5f) + { + hasPlayedDeathEffect = true; + EffectManager.SimpleMuzzleFlash(deathEffect, base.gameObject, "Center", transmit: false); + } + if (stopwatch >= duration) + { + EntityState.Destroy(base.gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/DoubleSlash.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/DoubleSlash.cs new file mode 100644 index 0000000..5b07f4f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/DoubleSlash.cs @@ -0,0 +1,128 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ImpMonster; + +public class DoubleSlash : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float procCoefficient; + + public static float selfForce; + + public static float forceMagnitude = 16f; + + public static GameObject hitEffectPrefab; + + public static GameObject swipeEffectPrefab; + + public static string enterSoundString; + + public static string slashSoundString; + + public static float walkSpeedPenaltyCoefficient; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private int slashCount; + + private Transform modelTransform; + + private static int DoubleSlashStateHash = Animator.StringToHash("DoubleSlash"); + + private static int DoubleSlashParamHash = Animator.StringToHash("DoubleSlash.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedPenaltyCoefficient; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + attack.procCoefficient = procCoefficient; + attack.damageType = DamageType.BleedOnHit; + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + if ((bool)modelAnimator) + { + PlayAnimation("Gesture, Additive", DoubleSlashStateHash, DoubleSlashParamHash, duration); + PlayAnimation("Gesture, Override", DoubleSlashStateHash, DoubleSlashParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration + 2f); + } + } + + public override void OnExit() + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + base.OnExit(); + } + + private void HandleSlash(string animatorParamName, string muzzleName, string hitBoxGroupName) + { + if (!(modelAnimator.GetFloat(animatorParamName) > 0.1f)) + { + return; + } + Util.PlaySound(slashSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(swipeEffectPrefab, base.gameObject, muzzleName, transmit: true); + slashCount++; + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == hitBoxGroupName); + } + if ((bool)base.healthComponent) + { + base.healthComponent.TakeDamageForce(base.characterDirection.forward * selfForce, alwaysApply: true); + } + attack.ResetIgnoredHealthComponents(); + if ((bool)base.characterDirection) + { + attack.forceVector = base.characterDirection.forward * forceMagnitude; + } + attack.Fire(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator) + { + switch (slashCount) + { + case 0: + HandleSlash("HandR.hitBoxActive", "SwipeRight", "HandR"); + break; + case 1: + HandleSlash("HandL.hitBoxActive", "SwipeLeft", "HandL"); + break; + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/FireSpines.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/FireSpines.cs new file mode 100644 index 0000000..a978dd3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/FireSpines.cs @@ -0,0 +1,74 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ImpMonster; + +public class FireSpines : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float baseDuration = 2f; + + public static float durationBetweenThrows = 0.1f; + + public static int spineCountMax = 3; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + private int spineCount; + + private float spineTimer; + + private float duration; + + private static int FireSpinesStateHash = Animator.StringToHash("FireSpines"); + + private static int FireSpinesParamHash = Animator.StringToHash("FireSpines.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture", FireSpinesStateHash, FireSpinesParamHash, duration); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + spineTimer += GetDeltaTime(); + if (spineTimer >= durationBetweenThrows / attackSpeedStat && spineCount < spineCountMax) + { + spineCount++; + Ray aimRay = GetAimRay(); + string muzzleName = "MuzzleMouth"; + spineTimer -= durationBetweenThrows / attackSpeedStat; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/SpawnState.cs new file mode 100644 index 0000000..46f6987 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ImpMonster/SpawnState.cs @@ -0,0 +1,45 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ImpMonster; + +public class SpawnState : BaseState +{ + private float stopwatch; + + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "Base", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Active.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Active.cs new file mode 100644 index 0000000..130b775 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Active.cs @@ -0,0 +1,64 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class Active : BaseSafeWardState +{ + [SerializeField] + public float radius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + private InfiniteTowerRun run; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)safeWardController) + { + safeWardController.SetIndicatorEnabled(enabled: false); + } + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)purchaseInteraction) + { + purchaseInteraction.SetAvailable(newAvailable: false); + } + if ((bool)zone) + { + zone.Networkradius = radius; + } + run = Run.instance as InfiniteTowerRun; + } + + public void SelfDestruct() + { + if (NetworkServer.active) + { + outer.SetNextState(new SelfDestruct()); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)zone && (bool)run) + { + float num = 1f; + if ((bool)run.waveController) + { + num = run.waveController.zoneRadiusPercentage; + } + zone.Networkradius = radius * num; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/AwaitingActivation.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/AwaitingActivation.cs new file mode 100644 index 0000000..ec7b809 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/AwaitingActivation.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class AwaitingActivation : BaseSafeWardState +{ + [SerializeField] + public float radius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)purchaseInteraction) + { + purchaseInteraction.SetAvailable(newAvailable: true); + } + if ((bool)zone) + { + zone.Networkradius = radius; + } + } + + public void Activate() + { + if (NetworkServer.active) + { + outer.SetNextState(new Active()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/AwaitingPortalUse.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/AwaitingPortalUse.cs new file mode 100644 index 0000000..cb1c3ea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/AwaitingPortalUse.cs @@ -0,0 +1,34 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class AwaitingPortalUse : BaseSafeWardState +{ + [SerializeField] + public float radius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)purchaseInteraction) + { + purchaseInteraction.SetAvailable(newAvailable: false); + } + if ((bool)zone) + { + zone.Networkradius = radius; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/BaseSafeWardState.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/BaseSafeWardState.cs new file mode 100644 index 0000000..6c1f50f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/BaseSafeWardState.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class BaseSafeWardState : EntityState +{ + protected PurchaseInteraction purchaseInteraction; + + protected VerticalTubeZone zone; + + protected Animator animator; + + [SerializeField] + public string objectiveToken; + + private GenericObjectiveProvider genericObjectiveProvider; + + protected InfiniteTowerSafeWardController safeWardController; + + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction = GetComponent(); + zone = GetComponent(); + animator = base.gameObject.GetComponentInChildren(); + safeWardController = base.gameObject.GetComponent(); + if (!string.IsNullOrEmpty(objectiveToken)) + { + genericObjectiveProvider = base.gameObject.AddComponent(); + genericObjectiveProvider.objectiveToken = objectiveToken; + } + } + + public override void PlayAnimation(string layerName, string animationStateName) + { + if ((bool)animator && !string.IsNullOrEmpty(layerName)) + { + EntityState.PlayAnimationOnAnimator(animator, layerName, animationStateName); + } + } + + public override void OnExit() + { + if ((bool)genericObjectiveProvider) + { + EntityState.Destroy(genericObjectiveProvider); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Burrow.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Burrow.cs new file mode 100644 index 0000000..7049ece --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Burrow.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class Burrow : BaseSafeWardState +{ + [SerializeField] + public float duration; + + [SerializeField] + public float radius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)zone) + { + zone.Networkradius = radius; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextState(new AwaitingActivation()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/CorrallingPlayers.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/CorrallingPlayers.cs new file mode 100644 index 0000000..4aca084 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/CorrallingPlayers.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class CorrallingPlayers : BaseSafeWardState +{ + [SerializeField] + public float duration; + + [SerializeField] + public float initialRadius; + + [SerializeField] + public float finalRadius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)purchaseInteraction) + { + purchaseInteraction.SetAvailable(newAvailable: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)zone) + { + float t = Mathf.Min(1f, base.fixedAge / duration); + zone.Networkradius = Mathf.Lerp(initialRadius, finalRadius, t); + } + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextState(new AwaitingActivation()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/SelfDestruct.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/SelfDestruct.cs new file mode 100644 index 0000000..91aae53 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/SelfDestruct.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class SelfDestruct : BaseSafeWardState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Travelling.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Travelling.cs new file mode 100644 index 0000000..e704b3a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Travelling.cs @@ -0,0 +1,251 @@ +using System.Collections.Generic; +using HG; +using RoR2; +using RoR2.Audio; +using RoR2.Navigation; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class Travelling : BaseSafeWardState +{ + [SerializeField] + public float radius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public float minDistanceToNewLocation; + + [SerializeField] + public float maxDistanceToNewLocation; + + [SerializeField] + public float travelSpeed; + + [SerializeField] + public float travelHeight; + + [SerializeField] + public float pathMaxSlope; + + [SerializeField] + public float pathMaxJumpHeight; + + [SerializeField] + public float pathMaxSpeed; + + [SerializeField] + public int pathNodeInclusionPeriod; + + [SerializeField] + public string voSoundString; + + [SerializeField] + public float minimumVoDelay; + + [SerializeField] + public float maximumVoDelay; + + [SerializeField] + public LoopSoundDef loopSoundDef; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + private const HullMask wardHullMask = HullMask.Human; + + private const HullClassification pathHullClassification = HullClassification.Human; + + private bool didFail; + + private NodeGraph groundNodeGraph; + + private List potentialEndNodes; + + private List catmullRomPoints = new List(); + + private Vector3 rotationVelocity; + + private Path groundPath; + + private int catmullRomIndex; + + private CatmullRom3 currentCurve; + + private float tCurve; + + private float voTimer; + + private Xoroshiro128Plus rng; + + public Travelling() + { + } + + public Travelling(Xoroshiro128Plus rng) + { + this.rng = rng; + } + + public override void OnEnter() + { + base.OnEnter(); + didFail = false; + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + ResetVoTimer(); + if ((bool)loopSoundDef) + { + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSoundDef); + } + if ((bool)zone) + { + zone.Networkradius = radius; + } + if (NetworkServer.active) + { + groundNodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + potentialEndNodes = groundNodeGraph.FindNodesInRangeWithFlagConditions(base.transform.position, 0f, minDistanceToNewLocation, HullMask.Human, NodeFlags.TeleporterOK, NodeFlags.None, preventOverhead: false); + Util.ShuffleList(potentialEndNodes, rng); + List list = groundNodeGraph.FindNodesInRangeWithFlagConditions(base.transform.position, minDistanceToNewLocation, maxDistanceToNewLocation, HullMask.Human, NodeFlags.TeleporterOK, NodeFlags.None, preventOverhead: false); + Util.ShuffleList(list, rng); + potentialEndNodes.AddRange(list); + groundPath = new Path(groundNodeGraph); + } + } + + public override void OnExit() + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + voTimer -= GetDeltaTime(); + if (voTimer <= 0f) + { + ResetVoTimer(); + Util.PlaySound(voSoundString, base.gameObject); + } + if (!NetworkServer.active) + { + return; + } + if (!didFail) + { + if (currentCurve == null) + { + if (potentialEndNodes.Count > 0) + { + EvaluateNextEndpoint(); + } + else + { + didFail = true; + Debug.LogError("SafeWard failed to find endpoint!"); + } + } + else + { + tCurve = currentCurve.AdvanceTByDistance(tCurve, travelSpeed * GetDeltaTime()); + tCurve = Mathf.Min(1f, tCurve); + base.transform.position = currentCurve.Evaluate(tCurve); + Vector3 vector = currentCurve.EvaluateDerivative(tCurve); + vector.y = 0f; + vector = vector.normalized; + Vector3 forward = Vector3.SmoothDamp(base.transform.forward, vector, ref rotationVelocity, 0.5f); + base.transform.forward = forward; + while (tCurve >= 1f && GetRemainingCurveSegmentCount() > 0) + { + tCurve -= 1f; + catmullRomIndex++; + UpdateCurveSegmentPoints(); + } + } + } + if (didFail || (GetRemainingCurveSegmentCount() <= 0 && tCurve >= 1f)) + { + outer.SetNextState(new Burrow()); + } + } + + private void EvaluateNextEndpoint() + { + int index = potentialEndNodes.Count - 1; + NodeGraph.NodeIndex nodeIndex = potentialEndNodes[index]; + potentialEndNodes.RemoveAt(index); + NodeGraph.PathRequest pathRequest = new NodeGraph.PathRequest + { + startPos = base.transform.position, + endPos = nodeIndex, + hullClassification = HullClassification.Human, + maxJumpHeight = pathMaxJumpHeight, + maxSlope = pathMaxSlope, + maxSpeed = pathMaxSpeed, + path = groundPath + }; + PathTask pathTask = groundNodeGraph.ComputePath(pathRequest); + if (pathTask == null || pathTask.status != PathTask.TaskStatus.Complete || !pathTask.wasReachable || pathTask.path.waypointsCount <= 1 || !groundNodeGraph.GetNodePosition(nodeIndex, out var _)) + { + return; + } + _ = 1f / (float)(pathTask.path.waypointsCount - 1); + for (int i = 0; i < pathTask.path.waypointsCount; i++) + { + if (i % pathNodeInclusionPeriod != 0 && i != pathTask.path.waypointsCount - 1) + { + continue; + } + Path.Waypoint waypoint = pathTask.path[i]; + if (groundNodeGraph.GetNodePosition(waypoint.nodeIndex, out var position2)) + { + if (i > 0 && i < pathTask.path.waypointsCount - 1) + { + position2.y += travelHeight; + } + catmullRomPoints.Add(position2); + } + } + if (catmullRomPoints.Count > 1) + { + Vector3 item = 2f * catmullRomPoints[0] - catmullRomPoints[1]; + catmullRomPoints.Insert(0, item); + Vector3 item2 = 2f * catmullRomPoints[catmullRomPoints.Count - 1] - catmullRomPoints[catmullRomPoints.Count - 2]; + catmullRomPoints.Add(item2); + DirectorCore.instance.AddOccupiedNode(groundNodeGraph, nodeIndex); + catmullRomIndex = 0; + currentCurve = new CatmullRom3(); + tCurve = 0f; + UpdateCurveSegmentPoints(); + } + else + { + catmullRomPoints.Clear(); + } + } + + private void UpdateCurveSegmentPoints() + { + currentCurve.SetPoints(catmullRomPoints[catmullRomIndex], catmullRomPoints[catmullRomIndex + 1], catmullRomPoints[catmullRomIndex + 2], catmullRomPoints[catmullRomIndex + 3]); + } + + private int GetRemainingCurveSegmentCount() + { + return catmullRomPoints.Count - 4 - catmullRomIndex; + } + + private void ResetVoTimer() + { + voTimer = Random.Range(minimumVoDelay, maximumVoDelay); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Unburrow.cs b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Unburrow.cs new file mode 100644 index 0000000..49fa209 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.InfiniteTowerSafeWard/Unburrow.cs @@ -0,0 +1,62 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.InfiniteTowerSafeWard; + +public class Unburrow : BaseSafeWardState +{ + [SerializeField] + public float duration; + + [SerializeField] + public float radius; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + private Xoroshiro128Plus rng; + + public Unburrow() + { + } + + public Unburrow(Xoroshiro128Plus rng) + { + this.rng = rng; + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)safeWardController) + { + safeWardController.SetIndicatorEnabled(enabled: true); + } + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)purchaseInteraction) + { + purchaseInteraction.SetAvailable(newAvailable: false); + } + if ((bool)zone) + { + zone.Networkradius = radius; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + outer.SetNextState(new Travelling(rng)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/GoldBeaconBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/GoldBeaconBaseState.cs new file mode 100644 index 0000000..6307ad9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/GoldBeaconBaseState.cs @@ -0,0 +1,37 @@ +using RoR2; +using RoR2.Hologram; +using UnityEngine; + +namespace EntityStates.Interactables.GoldBeacon; + +public class GoldBeaconBaseState : BaseState +{ + protected void SetReady(bool ready) + { + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + PrintController component = modelTransform.GetComponent(); + component.paused = !ready; + if (!ready) + { + component.age = 0f; + } + ChildLocator component2 = modelTransform.GetComponent(); + if ((bool)component2) + { + component2.FindChild("Purchased").gameObject.SetActive(ready); + } + } + PurchaseInteraction component3 = GetComponent(); + if ((bool)component3) + { + component3.SetAvailable(!ready); + } + HologramProjector component4 = GetComponent(); + if ((bool)component4) + { + component4.hologramPivot.gameObject.SetActive(!ready); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/NotReady.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/NotReady.cs new file mode 100644 index 0000000..d9ae660 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/NotReady.cs @@ -0,0 +1,20 @@ +namespace EntityStates.Interactables.GoldBeacon; + +public class NotReady : GoldBeaconBaseState +{ + public static int count { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + SetReady(ready: false); + SetPingable(value: true); + count++; + } + + public override void OnExit() + { + count--; + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/Ready.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/Ready.cs new file mode 100644 index 0000000..3df250c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.GoldBeacon/Ready.cs @@ -0,0 +1,33 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Interactables.GoldBeacon; + +public class Ready : GoldBeaconBaseState +{ + public static GameObject activationEffectPrefab; + + public static int count { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + SetReady(ready: true); + SetPingable(value: false); + count++; + } + + public override void OnExit() + { + count--; + if (!outer.destroying) + { + EffectManager.SpawnEffect(activationEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = 10f + }, transmit: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/EndingGame.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/EndingGame.cs new file mode 100644 index 0000000..da85a65 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/EndingGame.cs @@ -0,0 +1,90 @@ +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Interactables.MSObelisk; + +public class EndingGame : BaseState +{ + public static GameObject destroyEffectPrefab; + + public static float timeBetweenDestroy; + + public static float timeUntilEndGame; + + private float destroyTimer; + + private float endGameTimer; + + private bool beginEndingGame; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + FixedUpdateServer(); + } + } + + private void FixedUpdateServer() + { + destroyTimer -= GetDeltaTime(); + if (!beginEndingGame) + { + if (!(destroyTimer <= 0f)) + { + return; + } + destroyTimer = timeBetweenDestroy; + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(TeamIndex.Player); + if (teamMembers.Count > 0) + { + GameObject gameObject = teamMembers[0].gameObject; + CharacterBody component = gameObject.GetComponent(); + if ((bool)component) + { + EffectManager.SpawnEffect(destroyEffectPrefab, new EffectData + { + origin = component.corePosition, + scale = component.radius + }, transmit: true); + EntityState.Destroy(gameObject.gameObject); + } + } + else + { + beginEndingGame = true; + } + } + else + { + endGameTimer += GetDeltaTime(); + if (endGameTimer >= timeUntilEndGame && (bool)Run.instance) + { + DoFinalAction(); + } + } + } + + private void DoFinalAction() + { + bool flag = false; + for (int i = 0; i < CharacterMaster.readOnlyInstancesList.Count; i++) + { + if (CharacterMaster.readOnlyInstancesList[i].inventory.GetItemCount(RoR2Content.Items.LunarTrinket) > 0) + { + flag = true; + break; + } + } + if (flag) + { + outer.SetNextState(new TransitionToNextStage()); + return; + } + Run.instance.BeginGameOver(RoR2Content.GameEndings.ObliterationEnding); + outer.SetNextState(new Idle()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/ReadyToEndGame.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/ReadyToEndGame.cs new file mode 100644 index 0000000..1d12995 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/ReadyToEndGame.cs @@ -0,0 +1,50 @@ +using System.Collections.ObjectModel; +using RoR2; + +namespace EntityStates.Interactables.MSObelisk; + +public class ReadyToEndGame : BaseState +{ + public static string chargeupChildString; + + public static string chargeupSoundString; + + public static float chargeupDuration; + + private ChildLocator childLocator; + + private PurchaseInteraction purchaseInteraction; + + private bool ready; + + public override void OnEnter() + { + base.OnEnter(); + childLocator = GetComponent(); + purchaseInteraction = GetComponent(); + purchaseInteraction.NetworkcontextToken = "MSOBELISK_CONTEXT_CONFIRMATION"; + purchaseInteraction.Networkavailable = false; + childLocator.FindChild(chargeupChildString).gameObject.SetActive(value: true); + Util.PlaySound(chargeupSoundString, base.gameObject); + ReadOnlyCollection instances = PlayerCharacterMasterController.instances; + for (int i = 0; i < instances.Count; i++) + { + instances[i].master.preventGameOver = true; + } + for (int j = 0; j < CameraRigController.readOnlyInstancesList.Count; j++) + { + CameraRigController.readOnlyInstancesList[j].disableSpectating = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= chargeupDuration && !ready) + { + ready = true; + purchaseInteraction.Networkavailable = true; + base.gameObject.GetComponent().mainStateType = new SerializableEntityStateType(typeof(EndingGame)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/TransitionToNextStage.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/TransitionToNextStage.cs new file mode 100644 index 0000000..bd90e96 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.MSObelisk/TransitionToNextStage.cs @@ -0,0 +1,19 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.Interactables.MSObelisk; + +public class TransitionToNextStage : BaseState +{ + public static float duration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + Stage.instance.BeginAdvanceStage(SceneCatalog.GetSceneDefFromSceneName("limbo")); + outer.SetNextState(new Idle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Interactables.StoneGate/Opening.cs b/ilspy_dump/ror2_csproj/EntityStates.Interactables.StoneGate/Opening.cs new file mode 100644 index 0000000..a6801f7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Interactables.StoneGate/Opening.cs @@ -0,0 +1,77 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Interactables.StoneGate; + +public class Opening : BaseState +{ + public static string leftGateChildLocatorEntry; + + public static string rightGateChildLocatorEntry; + + public static AnimationCurve doorPositionCurve; + + public static float duration; + + public static string doorBeginOpenEffectChildLocatorEntry; + + public static string doorBeginOpenSoundString; + + public static string doorFinishedOpenEffectChildLocatorEntry; + + public static string doorFinishedOpenSoundString; + + private ChildLocator childLocator; + + private bool doorIsOpen; + + private Transform leftGateTransform; + + private Transform rightGateTransform; + + public override void OnEnter() + { + base.OnEnter(); + childLocator = GetComponent(); + childLocator.FindChild(doorBeginOpenEffectChildLocatorEntry).gameObject.SetActive(value: true); + Util.PlaySound(doorBeginOpenSoundString, base.gameObject); + if (NetworkServer.active) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "STONEGATE_OPEN" + }); + } + } + + public override void Update() + { + base.Update(); + UpdateGateTransform(ref leftGateTransform, leftGateChildLocatorEntry); + UpdateGateTransform(ref rightGateTransform, rightGateChildLocatorEntry); + } + + private void UpdateGateTransform(ref Transform gateTransform, string childLocatorString) + { + if (!gateTransform) + { + gateTransform = childLocator.FindChild(childLocatorString); + return; + } + Vector3 localPosition = gateTransform.localPosition; + gateTransform.localPosition = new Vector3(localPosition.x, localPosition.y, doorPositionCurve.Evaluate(base.age / duration)); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && !doorIsOpen) + { + doorIsOpen = true; + Util.PlaySound(doorFinishedOpenSoundString, base.gameObject); + childLocator.FindChild(doorBeginOpenEffectChildLocatorEntry).gameObject.SetActive(value: false); + childLocator.FindChild(doorFinishedOpenEffectChildLocatorEntry).gameObject.SetActive(value: true); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Jellyfish/Dash.cs b/ilspy_dump/ror2_csproj/EntityStates.Jellyfish/Dash.cs new file mode 100644 index 0000000..39a5ebb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Jellyfish/Dash.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace EntityStates.Jellyfish; + +public class Dash : BaseState +{ + public static float duration = 1.8f; + + public static float speedCoefficient = 2f; + + private Animator modelAnimator; + + private static int swimrateParamHash = Animator.StringToHash("swim.rate"); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = base.rigidbodyMotor.rigid.transform.forward * base.characterBody.moveSpeed * speedCoefficient; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.rigidbodyMotor && (bool)modelAnimator) + { + modelAnimator.SetFloat(swimrateParamHash, Vector3.Magnitude(base.rigidbodyMotor.rigid.velocity)); + } + if (base.fixedAge >= duration) + { + outer.SetNextState(new SwimState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Jellyfish/SwimState.cs b/ilspy_dump/ror2_csproj/EntityStates.Jellyfish/SwimState.cs new file mode 100644 index 0000000..5eafce2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Jellyfish/SwimState.cs @@ -0,0 +1,82 @@ +using UnityEngine; + +namespace EntityStates.Jellyfish; + +public class SwimState : BaseState +{ + private Animator modelAnimator; + + private bool skill1InputReceived; + + private bool skill2InputReceived; + + private bool skill3InputReceived; + + private bool skill4InputReceived; + + private bool jumpInputReceived; + + private static int swimrateParamHash = Animator.StringToHash("swim.rate"); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + } + + public override void Update() + { + base.Update(); + if ((bool)base.inputBank) + { + skill1InputReceived = base.inputBank.skill1.down; + skill2InputReceived |= base.inputBank.skill2.down; + skill3InputReceived |= base.inputBank.skill3.down; + skill4InputReceived |= base.inputBank.skill4.down; + jumpInputReceived |= base.inputBank.jump.down; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + if ((bool)base.inputBank) + { + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = base.inputBank.moveVector * base.characterBody.moveSpeed; + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(swimrateParamHash, Vector3.Magnitude(base.rigidbodyMotor.rigid.velocity)); + } + } + if ((bool)base.rigidbodyDirection) + { + base.rigidbodyDirection.aimDirection = GetAimRay().direction; + } + } + if ((bool)base.skillLocator) + { + if ((bool)base.skillLocator.primary && skill1InputReceived) + { + base.skillLocator.primary.ExecuteIfReady(); + } + if ((bool)base.skillLocator.secondary && skill2InputReceived) + { + base.skillLocator.secondary.ExecuteIfReady(); + } + if ((bool)base.skillLocator.utility && skill3InputReceived) + { + base.skillLocator.utility.ExecuteIfReady(); + } + if ((bool)base.skillLocator.special && skill4InputReceived) + { + base.skillLocator.special.ExecuteIfReady(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/DeathState.cs new file mode 100644 index 0000000..9b554d9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/DeathState.cs @@ -0,0 +1,41 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.JellyfishMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject enterEffectPrefab; + + public override void OnEnter() + { + base.OnEnter(); + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + + protected override void CreateDeathEffects() + { + base.CreateDeathEffects(); + if ((bool)enterEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(enterEffectPrefab)) + { + EffectManager.SimpleEffect(enterEffectPrefab, base.transform.position, base.transform.rotation, transmit: false); + } + else + { + EffectManager.GetAndActivatePooledEffect(enterEffectPrefab, base.transform.position, base.transform.rotation); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/JellyNova.cs b/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/JellyNova.cs new file mode 100644 index 0000000..bfb7091 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/JellyNova.cs @@ -0,0 +1,188 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.JellyfishMonster; + +public class JellyNova : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargingEffectPrefab; + + public static GameObject novaEffectPrefab; + + public static string chargingSoundString; + + public static string novaSoundString; + + public static float novaDamageCoefficient; + + public static float novaRadius; + + public static float novaForce; + + private bool hasExploded; + + private float duration; + + private float stopwatch; + + private GameObject chargeEffect; + + private PrintController printController; + + private uint soundID; + + private Vector3 _cachedScale = Vector3.one; + + private BlastAttack attack; + + private EffectData _effectData; + + private EffectManagerHelper _emh_chargeEffect; + + public override void Reset() + { + base.Reset(); + hasExploded = false; + duration = 0f; + chargeEffect = null; + printController = null; + soundID = 0u; + if (attack != null) + { + attack.Reset(); + } + if (_effectData != null) + { + _effectData.Reset(); + } + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayCrossfade("Body", "Nova", "Nova.playbackRate", duration, 0.1f); + soundID = Util.PlaySound(chargingSoundString, base.gameObject); + if ((bool)chargingEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargingEffectPrefab)) + { + chargeEffect = Object.Instantiate(chargingEffectPrefab, base.transform.position, base.transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(chargingEffectPrefab, base.transform.position, base.transform.rotation); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.parent = base.transform; + _cachedScale.x = novaRadius; + _cachedScale.y = novaRadius; + _cachedScale.z = novaRadius; + chargeEffect.transform.localScale = _cachedScale; + chargeEffect.GetComponent().newDuration = duration; + } + if ((bool)modelTransform) + { + printController = modelTransform.GetComponent(); + if ((bool)printController) + { + printController.enabled = true; + printController.printTime = duration; + } + } + } + + protected void DestroyChargeEffect() + { + if ((bool)chargeEffect) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + _emh_chargeEffect = null; + chargeEffect = null; + } + } + + public override void OnExit() + { + base.OnExit(); + AkSoundEngine.StopPlayingID(soundID); + DestroyChargeEffect(); + if ((bool)printController) + { + printController.enabled = false; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority && !hasExploded) + { + Detonate(); + } + } + + private void Detonate() + { + hasExploded = true; + Util.PlaySound(novaSoundString, base.gameObject); + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + DestroyChargeEffect(); + if ((bool)novaEffectPrefab) + { + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.origin = base.transform.position; + _effectData.scale = novaRadius; + EffectManager.SpawnEffect(novaEffectPrefab, _effectData, transmit: true); + } + if (attack == null) + { + attack = new BlastAttack(); + } + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * novaDamageCoefficient; + attack.baseForce = novaForce; + attack.position = base.transform.position; + attack.radius = novaRadius; + attack.procCoefficient = 2f; + attack.attackerFiltering = AttackerFiltering.NeverHitSelf; + attack.Fire(); + if ((bool)base.healthComponent) + { + base.healthComponent.Suicide(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/SpawnState.cs new file mode 100644 index 0000000..46dfae2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.JellyfishMonster/SpawnState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.JellyfishMonster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/AimState.cs b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/AimState.cs new file mode 100644 index 0000000..006e021 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/AimState.cs @@ -0,0 +1,73 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.LaserTurbine; + +public class AimState : LaserTurbineBaseState +{ + public static float targetAcquisitionRadius; + + private bool foundTarget; + + protected override bool shouldFollow => false; + + public override void OnEnter() + { + base.OnEnter(); + if (!base.isAuthority) + { + return; + } + TeamMask enemyTeams = TeamMask.GetEnemyTeams(base.ownerBody.teamComponent.teamIndex); + HurtBox[] hurtBoxes = new SphereSearch + { + radius = targetAcquisitionRadius, + mask = LayerIndex.entityPrecise.mask, + origin = base.transform.position, + queryTriggerInteraction = QueryTriggerInteraction.UseGlobal + }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(enemyTeams).OrderCandidatesByDistance() + .FilterCandidatesByDistinctHurtBoxEntities() + .GetHurtBoxes(); + float blastRadius = FireMainBeamState.secondBombPrefab.GetComponent().blastRadius; + int num = -1; + int num2 = 0; + for (int i = 0; i < hurtBoxes.Length; i++) + { + HurtBox[] hurtBoxes2 = new SphereSearch + { + radius = blastRadius, + mask = LayerIndex.entityPrecise.mask, + origin = hurtBoxes[i].transform.position, + queryTriggerInteraction = QueryTriggerInteraction.UseGlobal + }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(enemyTeams).FilterCandidatesByDistinctHurtBoxEntities() + .GetHurtBoxes(); + if (hurtBoxes2.Length > num2) + { + num = i; + num2 = hurtBoxes2.Length; + } + } + if (num != -1) + { + base.simpleRotateToDirection.targetRotation = Quaternion.LookRotation(hurtBoxes[num].transform.position - base.transform.position); + foundTarget = true; + } + } + + public override void Update() + { + base.Update(); + if (base.isAuthority) + { + if (foundTarget) + { + outer.SetNextState(new ChargeMainBeamState()); + } + else + { + outer.SetNextState(new ReadyState()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/ChargeMainBeamState.cs b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/ChargeMainBeamState.cs new file mode 100644 index 0000000..4ae468a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/ChargeMainBeamState.cs @@ -0,0 +1,57 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LaserTurbine; + +public class ChargeMainBeamState : LaserTurbineBaseState +{ + public static float baseDuration; + + public static GameObject beamIndicatorPrefab; + + private GameObject beamIndicatorInstance; + + private ChildLocator beamIndicatorChildLocator; + + private Transform beamIndicatorEndTransform; + + protected override bool shouldFollow => false; + + public override void OnEnter() + { + base.OnEnter(); + beamIndicatorInstance = Object.Instantiate(beamIndicatorPrefab, GetMuzzleTransform(), worldPositionStays: false); + beamIndicatorChildLocator = beamIndicatorInstance.GetComponent(); + if ((bool)beamIndicatorChildLocator) + { + beamIndicatorEndTransform = beamIndicatorChildLocator.FindChild("End"); + } + } + + public override void OnExit() + { + EntityState.Destroy(beamIndicatorInstance); + base.OnExit(); + } + + public override void Update() + { + base.Update(); + if (base.isAuthority && base.fixedAge >= baseDuration) + { + outer.SetNextState(new FireMainBeamState()); + } + if ((bool)beamIndicatorInstance && (bool)beamIndicatorEndTransform) + { + float num = 1000f; + Ray aimRay = GetAimRay(); + _ = beamIndicatorInstance.transform.parent.position; + Vector3 point = aimRay.GetPoint(num); + if (Util.CharacterRaycast(base.ownerBody.gameObject, aimRay, out var hitInfo, num, (int)LayerIndex.entityPrecise.mask | (int)LayerIndex.world.mask, QueryTriggerInteraction.UseGlobal)) + { + point = hitInfo.point; + } + beamIndicatorEndTransform.transform.position = point; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/FireMainBeamState.cs b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/FireMainBeamState.cs new file mode 100644 index 0000000..cb11f5e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/FireMainBeamState.cs @@ -0,0 +1,190 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LaserTurbine; + +public class FireMainBeamState : LaserTurbineBaseState +{ + public static float baseDuration; + + public static float mainBeamDamageCoefficient; + + public static float mainBeamProcCoefficient; + + public static float mainBeamForce; + + public static float mainBeamRadius; + + public static float mainBeamMaxDistance; + + public static GameObject forwardBeamTracerEffect; + + public static GameObject backwardBeamTracerEffect; + + public static GameObject mainBeamImpactEffect; + + public static GameObject secondBombPrefab; + + public static float secondBombDamageCoefficient; + + private Ray initialAimRay; + + private Vector3 beamHitPosition; + + private bool isCrit; + + protected override bool shouldFollow => true; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + initialAimRay = GetAimRay(); + } + if (NetworkServer.active) + { + isCrit = base.ownerBody.RollCrit(); + FireBeamServer(initialAimRay, forwardBeamTracerEffect, mainBeamMaxDistance, isInitialBeam: true); + } + base.laserTurbineController.showTurbineDisplay = false; + } + + public override void Update() + { + base.Update(); + if (base.isAuthority && base.fixedAge >= baseDuration) + { + outer.SetNextState(new RechargeState()); + } + } + + public override void OnExit() + { + if (NetworkServer.active && !outer.destroying) + { + Vector3 direction = initialAimRay.origin - beamHitPosition; + Ray aimRay = new Ray(beamHitPosition, direction); + FireBeamServer(aimRay, backwardBeamTracerEffect, direction.magnitude, isInitialBeam: false); + } + base.laserTurbineController.showTurbineDisplay = true; + base.OnExit(); + } + + private void FireBeamServer(Ray aimRay, GameObject tracerEffectPrefab, float maxDistance, bool isInitialBeam) + { + bool didHit = false; + BulletAttack obj = new BulletAttack + { + origin = aimRay.origin, + aimVector = aimRay.direction, + bulletCount = 1u, + damage = GetDamage() * mainBeamDamageCoefficient, + damageColorIndex = DamageColorIndex.Item, + damageType = DamageType.Generic, + falloffModel = BulletAttack.FalloffModel.None, + force = mainBeamForce, + hitEffectPrefab = mainBeamImpactEffect, + HitEffectNormal = false, + hitMask = LayerIndex.entityPrecise.mask, + isCrit = isCrit, + maxDistance = maxDistance, + minSpread = 0f, + maxSpread = 0f, + muzzleName = "", + owner = base.ownerBody.gameObject, + procChainMask = default(ProcChainMask), + procCoefficient = mainBeamProcCoefficient, + queryTriggerInteraction = QueryTriggerInteraction.UseGlobal, + radius = mainBeamRadius, + smartCollision = true, + sniper = false, + spreadPitchScale = 1f, + spreadYawScale = 1f, + stopperMask = LayerIndex.world.mask, + tracerEffectPrefab = (isInitialBeam ? tracerEffectPrefab : null), + weapon = base.gameObject + }; + TeamIndex teamIndex = base.ownerBody.teamComponent.teamIndex; + obj.hitCallback = delegate(BulletAttack _bulletAttack, ref BulletAttack.BulletHit info) + { + bool flag = BulletAttack.defaultHitCallback(_bulletAttack, ref info); + if (!isInitialBeam) + { + return true; + } + if (flag) + { + HealthComponent healthComponent = (info.hitHurtBox ? info.hitHurtBox.healthComponent : null); + if ((bool)healthComponent && healthComponent.alive && info.hitHurtBox.teamIndex != teamIndex) + { + flag = false; + } + } + if (!flag) + { + didHit = true; + beamHitPosition = info.point; + } + return flag; + }; + obj.filterCallback = delegate(BulletAttack _bulletAttack, ref BulletAttack.BulletHit info) + { + return (!info.entityObject || (object)info.entityObject != _bulletAttack.owner) && BulletAttack.defaultFilterCallback(_bulletAttack, ref info); + }; + obj.Fire(); + if (!didHit) + { + if (Physics.Raycast(aimRay, out var hitInfo, mainBeamMaxDistance, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + didHit = true; + beamHitPosition = hitInfo.point; + } + else + { + beamHitPosition = aimRay.GetPoint(mainBeamMaxDistance); + } + } + if (didHit && isInitialBeam) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = secondBombPrefab; + fireProjectileInfo.owner = base.ownerBody.gameObject; + fireProjectileInfo.position = beamHitPosition - aimRay.direction * 0.5f; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.damage = GetDamage() * secondBombDamageCoefficient; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Item; + fireProjectileInfo.crit = isCrit; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + if (!isInitialBeam) + { + EffectData effectData = new EffectData + { + origin = aimRay.origin, + start = base.transform.position + }; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + Vector3 origin = initialAimRay.origin; + Vector3 direction = initialAimRay.direction; + writer.Write(origin); + writer.Write(direction); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + Vector3 origin = reader.ReadVector3(); + Vector3 direction = reader.ReadVector3(); + initialAimRay = new Ray(origin, direction); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/LaserTurbineBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/LaserTurbineBaseState.cs new file mode 100644 index 0000000..bde7322 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/LaserTurbineBaseState.cs @@ -0,0 +1,69 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LaserTurbine; + +public class LaserTurbineBaseState : EntityState +{ + private GenericOwnership genericOwnership; + + private SimpleLeash simpleLeash; + + private MemoizedGetComponent bodyGetComponent; + + protected LaserTurbineController laserTurbineController { get; private set; } + + protected SimpleRotateToDirection simpleRotateToDirection { get; private set; } + + protected CharacterBody ownerBody => bodyGetComponent.Get(genericOwnership?.ownerObject); + + protected virtual bool shouldFollow => true; + + public override void OnEnter() + { + base.OnEnter(); + genericOwnership = GetComponent(); + simpleLeash = GetComponent(); + simpleRotateToDirection = GetComponent(); + laserTurbineController = GetComponent(); + } + + protected InputBankTest GetInputBank() + { + return ownerBody?.inputBank; + } + + protected Ray GetAimRay() + { + return new Ray(base.transform.position, base.transform.forward); + } + + protected Transform GetMuzzleTransform() + { + return base.transform; + } + + public override void Update() + { + base.Update(); + if ((bool)ownerBody && shouldFollow) + { + simpleLeash.leashOrigin = ownerBody.corePosition; + simpleRotateToDirection.targetRotation = Quaternion.LookRotation(ownerBody.inputBank.aimDirection); + } + } + + protected float GetDamage() + { + float num = 1f; + if ((bool)ownerBody) + { + num = ownerBody.damage; + if ((bool)ownerBody.inventory) + { + num *= (float)ownerBody.inventory.GetItemCount(RoR2Content.Items.LaserTurbine); + } + } + return num; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/ReadyState.cs b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/ReadyState.cs new file mode 100644 index 0000000..3577167 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/ReadyState.cs @@ -0,0 +1,15 @@ +namespace EntityStates.LaserTurbine; + +public class ReadyState : LaserTurbineBaseState +{ + public static float baseDuration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= baseDuration) + { + outer.SetNextState(new AimState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/RechargeState.cs b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/RechargeState.cs new file mode 100644 index 0000000..1059fac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LaserTurbine/RechargeState.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.LaserTurbine; + +public class RechargeState : LaserTurbineBaseState +{ + public static float baseDuration = 60f; + + public static int killChargesRequired = 4; + + public static int killChargeDuration = 4; + + public Run.FixedTimeStamp startTime { get; private set; } + + public Run.FixedTimeStamp readyTime { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + startTime = Run.FixedTimeStamp.now; + readyTime = startTime + baseDuration; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.ownerBody.GetBuffCount(RoR2Content.Buffs.LaserTurbineKillCharge) >= killChargesRequired) + { + if (NetworkServer.active) + { + base.laserTurbineController.ExpendCharge(); + } + outer.SetNextState(new ReadyState()); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(startTime); + writer.Write(readyTime); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + startTime = reader.ReadFixedTimeStamp(); + readyTime = reader.ReadFixedTimeStamp(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/ChargeMegaFireball.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/ChargeMegaFireball.cs new file mode 100644 index 0000000..5c98d82 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/ChargeMegaFireball.cs @@ -0,0 +1,99 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LemurianBruiserMonster; + +public class ChargeMegaFireball : BaseState +{ + public static float baseDuration = 1f; + + public static GameObject chargeEffectPrefab; + + public static string attackString; + + private float duration; + + private GameObject chargeInstance; + + private EffectManagerHelper _emh_chargeInstance; + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeInstance = null; + _emh_chargeInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Animator modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleMouth"); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance = _emh_chargeInstance.gameObject; + } + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + } + if ((bool)modelAnimator) + { + PlayCrossfade("Gesture, Additive", "ChargeMegaFireball", "ChargeMegaFireball.playbackRate", duration, 0.1f); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeInstance) + { + if (_emh_chargeInstance != null && _emh_chargeInstance.OwningPool != null) + { + _emh_chargeInstance.OwningPool.ReturnObject(_emh_chargeInstance); + } + else + { + EntityState.Destroy(chargeInstance); + } + chargeInstance = null; + _emh_chargeInstance = null; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireMegaFireball nextState = new FireMegaFireball(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/FireMegaFireball.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/FireMegaFireball.cs new file mode 100644 index 0000000..6e62d16 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/FireMegaFireball.cs @@ -0,0 +1,84 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.LemurianBruiserMonster; + +public class FireMegaFireball : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject muzzleflashEffectPrefab; + + public static int projectileCount = 3; + + public static float totalYawSpread = 5f; + + public static float baseDuration = 2f; + + public static float baseFireDuration = 0.2f; + + public static float damageCoefficient = 1.2f; + + public static float projectileSpeed; + + public static float force = 20f; + + public static string attackString; + + private float duration; + + private float fireDuration; + + private int projectilesFired; + + private static int FireMegaFireballStateHash = Animator.StringToHash("FireMegaFireball"); + + private static int FireMegaFireballParamHash = Animator.StringToHash("FireMegaFireball.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + fireDuration = baseFireDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", FireMegaFireballStateHash, FireMegaFireballParamHash, duration); + Util.PlaySound(attackString, base.gameObject); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + string muzzleName = "MuzzleMouth"; + if (base.isAuthority) + { + int num = Mathf.FloorToInt(base.fixedAge / fireDuration * (float)projectileCount); + if (projectilesFired <= num && projectilesFired < projectileCount) + { + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Ray aimRay = GetAimRay(); + float speedOverride = projectileSpeed; + float bonusYaw = (float)Mathf.FloorToInt((float)projectilesFired - (float)(projectileCount - 1) / 2f) / (float)(projectileCount - 1) * totalYawSpread; + Vector3 forward = Util.ApplySpread(aimRay.direction, 0f, 0f, 1f, 1f, bonusYaw); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, speedOverride); + projectilesFired++; + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/Flamebreath.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/Flamebreath.cs new file mode 100644 index 0000000..0ccc5cc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/Flamebreath.cs @@ -0,0 +1,232 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LemurianBruiserMonster; + +public class Flamebreath : BaseState +{ + public static GameObject flamethrowerEffectPrefab; + + public static GameObject impactEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float maxDistance; + + public static float radius; + + public static float baseEntryDuration = 1f; + + public static float baseExitDuration = 0.5f; + + public static float baseFlamethrowerDuration = 2f; + + public static float totalDamageCoefficient = 1.2f; + + public static float procCoefficientPerTick; + + public static float tickFrequency; + + public static float force = 20f; + + public static string startAttackSoundString; + + public static string endAttackSoundString; + + public static float ignitePercentChance; + + public static float maxSpread; + + private float tickDamageCoefficient; + + private float flamethrowerStopwatch; + + private float stopwatch; + + private float entryDuration; + + private float exitDuration; + + private float flamethrowerDuration; + + private bool hasBegunFlamethrower; + + private ChildLocator childLocator; + + private Transform flamethrowerEffectInstance; + + private Transform muzzleTransform; + + private bool isCrit; + + private BulletAttack bulletAttack; + + private EffectManagerHelper _emh_flamethrowerEffectInstance; + + private static int PrepFlamebreathStateHash = Animator.StringToHash("PrepFlamebreath"); + + private static int PrepFlamebreathParamHash = Animator.StringToHash("PrepFlamebreath.playbackRate"); + + private const float flamethrowerEffectBaseDistance = 16f; + + private static int FlamebreathStateHash = Animator.StringToHash("Flamebreath"); + + private static int FlamebreathParamHash = Animator.StringToHash("Flamebreath.playbackRate"); + + public override void Reset() + { + base.Reset(); + tickDamageCoefficient = 0f; + flamethrowerStopwatch = 0f; + stopwatch = 0f; + entryDuration = 0f; + exitDuration = 0f; + flamethrowerDuration = 0f; + hasBegunFlamethrower = false; + childLocator = null; + flamethrowerEffectInstance = null; + muzzleTransform = null; + isCrit = false; + if (bulletAttack != null) + { + bulletAttack.Reset(); + } + _emh_flamethrowerEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + entryDuration = baseEntryDuration / attackSpeedStat; + exitDuration = baseExitDuration / attackSpeedStat; + flamethrowerDuration = baseFlamethrowerDuration; + Transform modelTransform = GetModelTransform(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(entryDuration + flamethrowerDuration + 1f); + } + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + modelTransform.GetComponent().enabled = true; + } + float num = flamethrowerDuration * tickFrequency; + tickDamageCoefficient = totalDamageCoefficient / num; + if (base.isAuthority && (bool)base.characterBody) + { + isCrit = Util.CheckRoll(critStat, base.characterBody.master); + } + PlayAnimation("Gesture, Override", PrepFlamebreathStateHash, PrepFlamebreathParamHash, entryDuration); + } + + protected void DestroyFlameThrowerEffect() + { + if (flamethrowerEffectInstance != null) + { + if (_emh_flamethrowerEffectInstance != null && _emh_flamethrowerEffectInstance.OwningPool != null) + { + _emh_flamethrowerEffectInstance.OwningPool.ReturnObject(_emh_flamethrowerEffectInstance); + } + else + { + EntityState.Destroy(flamethrowerEffectInstance.gameObject); + } + flamethrowerEffectInstance = null; + _emh_flamethrowerEffectInstance = null; + } + } + + public override void OnExit() + { + Util.PlaySound(endAttackSoundString, base.gameObject); + PlayCrossfade("Gesture, Override", "BufferEmpty", 0.1f); + DestroyFlameThrowerEffect(); + base.OnExit(); + } + + private void FireFlame(string muzzleString) + { + GetAimRay(); + if (base.isAuthority && (bool)muzzleTransform) + { + if (bulletAttack == null) + { + bulletAttack = new BulletAttack(); + } + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = muzzleTransform.position; + bulletAttack.aimVector = muzzleTransform.forward; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = maxSpread; + bulletAttack.damage = tickDamageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.muzzleName = muzzleString; + bulletAttack.hitEffectPrefab = impactEffectPrefab; + bulletAttack.isCrit = isCrit; + bulletAttack.radius = radius; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.stopperMask = LayerIndex.world.mask; + bulletAttack.procCoefficient = procCoefficientPerTick; + bulletAttack.maxDistance = maxDistance; + bulletAttack.smartCollision = true; + bulletAttack.damageType = (Util.CheckRoll(ignitePercentChance, base.characterBody.master) ? DamageType.IgniteOnHit : DamageType.Generic); + bulletAttack.Fire(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= entryDuration && stopwatch < entryDuration + flamethrowerDuration && !hasBegunFlamethrower) + { + hasBegunFlamethrower = true; + Util.PlaySound(startAttackSoundString, base.gameObject); + PlayAnimation("Gesture, Override", FlamebreathStateHash, FlamebreathParamHash, flamethrowerDuration); + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild("MuzzleMouth"); + if (!EffectManager.ShouldUsePooledEffect(flamethrowerEffectPrefab)) + { + flamethrowerEffectInstance = Object.Instantiate(flamethrowerEffectPrefab, muzzleTransform).transform; + } + else + { + _emh_flamethrowerEffectInstance = EffectManager.GetAndActivatePooledEffect(flamethrowerEffectPrefab, muzzleTransform, inResetLocal: true); + flamethrowerEffectInstance = _emh_flamethrowerEffectInstance.gameObject.transform; + } + flamethrowerEffectInstance.transform.localPosition = Vector3.zero; + flamethrowerEffectInstance.GetComponent().newDuration = flamethrowerDuration; + } + } + if (stopwatch >= entryDuration + flamethrowerDuration && hasBegunFlamethrower) + { + hasBegunFlamethrower = false; + PlayCrossfade("Gesture, Override", "ExitFlamebreath", "ExitFlamebreath.playbackRate", exitDuration, 0.1f); + } + if (hasBegunFlamethrower) + { + flamethrowerStopwatch += Time.deltaTime; + if (flamethrowerStopwatch > 1f / tickFrequency) + { + flamethrowerStopwatch -= 1f / tickFrequency; + FireFlame("MuzzleCenter"); + } + } + else + { + DestroyFlameThrowerEffect(); + } + if (stopwatch >= flamethrowerDuration + entryDuration + exitDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/SpawnState.cs new file mode 100644 index 0000000..0f439b3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianBruiserMonster/SpawnState.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LemurianBruiserMonster; + +public class SpawnState : EntityState +{ + public static float duration = 2f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + GetModelAnimator(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "SpawnEffectOrigin", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/Bite.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/Bite.cs new file mode 100644 index 0000000..f1602da --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/Bite.cs @@ -0,0 +1,87 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LemurianMonster; + +public class Bite : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + public static GameObject hitEffectPrefab; + + public static GameObject biteEffectPrefab; + + public static string attackString; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private float duration; + + private bool hasBit; + + private static int BiteStateHash = Animator.StringToHash("Bite"); + + private static int BiteParamHash = Animator.StringToHash("Bite.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Bite"); + } + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", BiteStateHash, BiteParamHash, duration); + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)modelAnimator && modelAnimator.GetFloat("Bite.hitBoxActive") > 0.1f) + { + if (!hasBit) + { + EffectManager.SimpleMuzzleFlash(biteEffectPrefab, base.gameObject, "MuzzleMouth", transmit: true); + hasBit = true; + } + attack.forceVector = base.transform.forward * forceMagnitude; + attack.Fire(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/ChargeFireball.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/ChargeFireball.cs new file mode 100644 index 0000000..cf65916 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/ChargeFireball.cs @@ -0,0 +1,101 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LemurianMonster; + +public class ChargeFireball : BaseState +{ + public static float baseDuration = 1f; + + public static GameObject chargeVfxPrefab; + + public static string attackString; + + private float duration; + + private GameObject chargeVfxInstance; + + protected EffectManagerHelper _efhChargeEffect; + + private static int ChargeFireballStateHash = Animator.StringToHash("ChargeFireball"); + + private static int ChargeFireballParamHash = Animator.StringToHash("ChargeFireball.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeVfxInstance = null; + _efhChargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleMouth"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(chargeVfxPrefab)) + { + chargeVfxInstance = Object.Instantiate(chargeVfxPrefab, transform.position, transform.rotation); + } + else + { + _efhChargeEffect = EffectManager.GetAndActivatePooledEffect(chargeVfxPrefab, transform.position, transform.rotation); + chargeVfxInstance = _efhChargeEffect.gameObject; + } + chargeVfxInstance.transform.parent = transform; + } + } + } + PlayAnimation("Gesture", ChargeFireballStateHash, ChargeFireballParamHash, duration); + } + + public override void OnExit() + { + base.OnExit(); + if (!chargeVfxInstance) + { + return; + } + if (!EffectManager.UsePools) + { + EntityState.Destroy(chargeVfxInstance); + return; + } + if (_efhChargeEffect != null && _efhChargeEffect.OwningPool != null) + { + _efhChargeEffect.OwningPool.ReturnObject(_efhChargeEffect); + return; + } + if (_efhChargeEffect != null) + { + Debug.LogFormat("ChargeFireball has no owning pool {0} {1}", base.gameObject.name, base.gameObject.GetInstanceID()); + } + EntityState.Destroy(chargeVfxInstance); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireFireball nextState = new FireFireball(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/FireFireball.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/FireFireball.cs new file mode 100644 index 0000000..2bbe60c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/FireFireball.cs @@ -0,0 +1,63 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.LemurianMonster; + +public class FireFireball : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string attackString; + + private float duration; + + private static int FireFireballStateHash = Animator.StringToHash("FireFireball"); + + private static int FireFireballParamHash = Animator.StringToHash("FireFireball.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture", FireFireballStateHash, FireFireballParamHash, duration); + Util.PlaySound(attackString, base.gameObject); + Ray aimRay = GetAimRay(); + string muzzleName = "MuzzleMouth"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/LeapAttackState.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/LeapAttackState.cs new file mode 100644 index 0000000..ad94488 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/LeapAttackState.cs @@ -0,0 +1,71 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.LemurianMonster; + +public class LeapAttackState : BaseState +{ + public static float baseDuration = 3.5f; + + public static float damage = 10f; + + public static float forceMagnitude = 16f; + + private OverlapAttack attack; + + private Animator modelAnimator; + + private RootMotionAccumulator rootMotionAccumulator; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + rootMotionAccumulator = GetModelRootMotionAccumulator(); + modelAnimator = GetModelAnimator(); + duration = baseDuration / attackSpeedStat; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damage; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "LeapAttack"); + } + PlayCrossfade("Body", "LeapAttack", "LeapAttack.playbackRate", duration, 0.1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)rootMotionAccumulator) + { + Vector3 vector = rootMotionAccumulator.ExtractRootMotion(); + if (vector != Vector3.zero && base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.rootMotion += vector; + } + } + if (base.isAuthority) + { + attack.forceVector = (base.characterDirection ? (base.characterDirection.forward * forceMagnitude) : Vector3.zero); + if ((bool)modelAnimator && modelAnimator.GetFloat("LeapAttack.hitBoxActive") > 0.5f) + { + attack.Fire(); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/SpawnState.cs new file mode 100644 index 0000000..224ccf5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LemurianMonster/SpawnState.cs @@ -0,0 +1,44 @@ +using RoR2; + +namespace EntityStates.LemurianMonster; + +public class SpawnState : EntityState +{ + public static float duration = 2f; + + public static string spawnSoundString; + + public static string devotionHissSoundString; + + public static string devotionSpawnSoundString; + + public override void OnEnter() + { + base.OnEnter(); + CharacterBody component = base.gameObject.GetComponent(); + if ((component.bodyFlags & CharacterBody.BodyFlags.Devotion) != 0 && component.master.devotionInventoryPrefab != null) + { + Util.PlaySound(devotionHissSoundString, base.gameObject); + Util.PlaySound(devotionSpawnSoundString, base.gameObject); + } + else + { + Util.PlaySound(spawnSoundString, base.gameObject); + } + PlayAnimation("Body", "Spawn1", "Spawn1.playbackRate", duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LightningStorm/LightningStormState.cs b/ilspy_dump/ror2_csproj/EntityStates.LightningStorm/LightningStormState.cs new file mode 100644 index 0000000..3fc9188 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LightningStorm/LightningStormState.cs @@ -0,0 +1,241 @@ +using System; +using System.Collections.Generic; +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.LightningStorm; + +public class LightningStormState : BaseState +{ + [SerializeField] + public GameObject lightningInstancePrefab; + + public static int strikesPerSurvivor = 4; + + public static float minDistanceBetweenStrikes = 3f; + + public static float maxStrikeDistanceFromPlayer = 5f; + + public static float frequencyOfLightningStrikes = 8f; + + public static float timeBetweenIndividualStrikes = 0.2f; + + private List possibleNodesToTarget = new List(); + + private List possibleNodePositions = new List(); + + private float stormStopwatch; + + private float strikeStopwatch; + + private Queue positionsToStrike = new Queue(); + + private GameObject startPostProcessingObject; + + private PostProcessDuration startPostProcessDuration; + + private GameObject endPostProcessingObject; + + private PostProcessDuration endPostProcessDuration; + + private Action ExecuteNextStep; + + public override void OnEnter() + { + base.OnEnter(); + LightningStormController component = GetComponent(); + if ((bool)component) + { + startPostProcessingObject = component.startPostProcessingObject; + startPostProcessDuration = component.startPostProcessDuration; + endPostProcessingObject = component.endPostProcessingObject; + endPostProcessDuration = component.endPostProcessDuration; + } + HandleStartStorm(); + } + + public override void OnExit() + { + base.OnExit(); + HandleStopStorm(); + } + + private void HandleStartStorm() + { + ToggleStormVFX(b: true); + ExecuteNextStep = GenerateTargetPositions; + stormStopwatch = -1f; + } + + private void ToggleStormVFX(bool b) + { + if ((bool)startPostProcessingObject) + { + startPostProcessingObject.SetActive(b); + startPostProcessDuration.enabled = b; + } + if ((bool)endPostProcessingObject) + { + endPostProcessingObject.SetActive(!b); + endPostProcessDuration.enabled = !b; + } + } + + private void GenerateTargetPositions() + { + if (stormStopwatch > 0f) + { + return; + } + positionsToStrike.Clear(); + _ = minDistanceBetweenStrikes; + _ = minDistanceBetweenStrikes; + LightningStrikePattern lightningPattern = LightningStormController.lightningPattern; + if (lightningPattern == null) + { + Debug.LogWarning("No Lightning Storm pattern set up in the LightningStormController!"); + return; + } + if (!SceneInfo.instance || !SceneInfo.instance.groundNodes) + { + Debug.LogWarning("No ground nodes available, disabling lightning storm"); + HandleStopStorm(); + return; + } + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + possibleNodesToTarget.Clear(); + float num = 0f; + foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) + { + if (!(instance == null) && !(instance.master == null) && instance.master.GetBody() != null) + { + num += 1f; + } + } + num -= 1f; + foreach (PlayerCharacterMasterController instance2 in PlayerCharacterMasterController.instances) + { + CharacterBody body = instance2.master.GetBody(); + if (body == null || !body.hasAuthority) + { + continue; + } + Transform coreTransform = body.coreTransform; + Vector3 velocity = body.characterMotor.velocity; + float magnitude = new Vector3(velocity.x, 0f, velocity.z).magnitude; + velocity = velocity.normalized; + float num2 = magnitude; + foreach (LightningStormController.LightningStrikePoint lightningStrikePoint in lightningPattern.lightningStrikePoints) + { + float maxDistance = LightningStormController.GetMaxDistance(velocity, magnitude, lightningStrikePoint); + if (maxDistance > num2) + { + num2 = maxDistance; + } + } + num2 = Mathf.Max(num2, lightningPattern.maxAcceptableDistanceFromPredictedPoint * 2f); + possibleNodesToTarget = groundNodes.FindNodesInRange(coreTransform.position, 0f, num2, HullMask.Human); + possibleNodePositions.Clear(); + int count = possibleNodesToTarget.Count; + for (int i = 0; i < count; i++) + { + if (groundNodes.GetNodePosition(possibleNodesToTarget[i], out var position2)) + { + possibleNodePositions.Add(position2); + } + } + int count2 = lightningPattern.lightningStrikePoints.Count; + count2 -= (int)(num * lightningPattern.forEachAdditionalPlayerReduceStrikeTotalBy); + count2 = Mathf.Max(count2, 1); + foreach (LightningStormController.LightningStrikePoint lightningStrikePoint2 in lightningPattern.lightningStrikePoints) + { + if (positionsToStrike.Count >= count2) + { + break; + } + Vector3 position3 = LightningStormController.PredictPosition(coreTransform.position, coreTransform.forward, magnitude, lightningStrikePoint2); + if (TryPickBestNodePosition(position3, lightningPattern.maxAcceptableDistanceFromPredictedPoint, out var bestPosition2)) + { + positionsToStrike.Enqueue(bestPosition2); + } + } + } + ExecuteNextStep = FireNextStrike; + bool TryPickBestNodePosition(Vector3 position, float range, out Vector3 bestPosition) + { + int num3 = -1; + range *= range; + float num4 = float.MaxValue; + bestPosition = Vector3.zero; + int count3 = possibleNodePositions.Count; + Vector2 vector = new Vector2(position.x, position.z); + for (int j = 0; j < count3; j++) + { + float sqrMagnitude = (new Vector2(possibleNodePositions[j].x, possibleNodePositions[j].z) - vector).sqrMagnitude; + if (sqrMagnitude <= range && sqrMagnitude < num4) + { + num3 = j; + num4 = sqrMagnitude; + } + } + if (num3 != -1) + { + bestPosition = possibleNodePositions[num3]; + possibleNodePositions.RemoveAt(num3); + return true; + } + return false; + } + } + + private void FireNextStrike() + { + if (positionsToStrike.Count < 1) + { + stormStopwatch = LightningStormController.lightningPattern.frequencyOfLightningStrikes; + ExecuteNextStep = GenerateTargetPositions; + } + else if (!(strikeStopwatch > 0f)) + { + strikeStopwatch = LightningStormController.lightningPattern.timeBetweenIndividualStrikes; + LightningStormController.FireLightningBolt(positionsToStrike.Dequeue(), lightningInstancePrefab); + } + } + + private void WaitForNextStrike() + { + if (stormStopwatch <= 0f) + { + ExecuteNextStep = GenerateTargetPositions; + } + } + + private void HandleStopStorm() + { + ToggleStormVFX(b: false); + ExecuteNextStep = null; + } + + public override void Update() + { + float deltaTime = Time.deltaTime; + stormStopwatch -= deltaTime; + strikeStopwatch -= deltaTime; + ExecuteNextStep?.Invoke(); + } + + private void LightningStrikeAtPosition(Vector3 position) + { + GameObject gameObject = UnityEngine.Object.Instantiate(lightningInstancePrefab); + LightningStrikeInstance component = gameObject.GetComponent(); + if (!component) + { + Debug.Log("GameObject doesn't have a lightninginstance component!", gameObject); + } + else + { + component.Initialize(position, null); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/BaseChargeFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/BaseChargeFist.cs new file mode 100644 index 0000000..52b69be --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/BaseChargeFist.cs @@ -0,0 +1,205 @@ +using System; +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Loader; + +public class BaseChargeFist : BaseSkillState +{ + private class ArcVisualizer : IDisposable + { + private readonly Vector3[] points; + + private readonly float duration; + + private readonly GameObject arcVisualizerInstance; + + private readonly LineRenderer lineRenderer; + + public ArcVisualizer(GameObject arcVisualizerPrefab, float duration, int vertexCount) + { + arcVisualizerInstance = UnityEngine.Object.Instantiate(arcVisualizerPrefab); + lineRenderer = arcVisualizerInstance.GetComponent(); + lineRenderer.positionCount = vertexCount; + points = new Vector3[vertexCount]; + this.duration = duration; + } + + public void Dispose() + { + EntityState.Destroy(arcVisualizerInstance); + } + + public void SetParameters(Vector3 origin, Vector3 initialVelocity, float characterMaxSpeed, float characterAcceleration) + { + arcVisualizerInstance.transform.position = origin; + if (!lineRenderer.useWorldSpace) + { + Vector3 eulerAngles = Quaternion.LookRotation(initialVelocity).eulerAngles; + eulerAngles.x = 0f; + eulerAngles.z = 0f; + Quaternion rotation = Quaternion.Euler(eulerAngles); + arcVisualizerInstance.transform.rotation = rotation; + origin = Vector3.zero; + initialVelocity = Quaternion.Inverse(rotation) * initialVelocity; + } + else + { + arcVisualizerInstance.transform.rotation = Quaternion.LookRotation(Vector3.Cross(initialVelocity, Vector3.up)); + } + float y = Physics.gravity.y; + float num = duration / (float)points.Length; + Vector3 vector = origin; + Vector3 vector2 = initialVelocity; + float num2 = num; + float num3 = y * num2; + float maxDistanceDelta = characterAcceleration * num2; + for (int i = 0; i < points.Length; i++) + { + points[i] = vector; + Vector2 current = Util.Vector3XZToVector2XY(vector2); + current = Vector2.MoveTowards(current, Vector3.zero, maxDistanceDelta); + vector2.x = current.x; + vector2.z = current.y; + vector2.y += num3; + vector += vector2 * num2; + } + lineRenderer.SetPositions(points); + } + } + + public static GameObject arcVisualizerPrefab; + + public static float arcVisualizerSimulationLength; + + public static int arcVisualizerVertexCount; + + [SerializeField] + public float baseChargeDuration = 1f; + + public static float minChargeForChargedAttack; + + public static GameObject chargeVfxPrefab; + + public static string chargeVfxChildLocatorName; + + public static GameObject crosshairOverridePrefab; + + public static float walkSpeedCoefficient; + + public static string startChargeLoopSFXString; + + public static string endChargeLoopSFXString; + + public static string enterSFXString; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private Transform chargeVfxInstanceTransform; + + private int gauntlet; + + private uint soundID; + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int ChargePunchIntroStateHash = Animator.StringToHash("ChargePunchIntro"); + + private static int ChargePunchIntroParamHash = Animator.StringToHash("ChargePunchIntro.playbackRate"); + + protected float chargeDuration { get; private set; } + + protected float charge { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration / attackSpeedStat; + Util.PlaySound(enterSFXString, base.gameObject); + soundID = Util.PlaySound(startChargeLoopSFXString, base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnExit() + { + if ((bool)chargeVfxInstanceTransform) + { + EntityState.Destroy(chargeVfxInstanceTransform.gameObject); + PlayAnimation("Gesture, Additive", EmptyStateHash); + PlayAnimation("Gesture, Override", EmptyStateHash); + crosshairOverrideRequest?.Dispose(); + chargeVfxInstanceTransform = null; + } + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + Util.PlaySound(endChargeLoopSFXString, base.gameObject); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + AkSoundEngine.SetRTPCValueByPlayingID("loaderShift_chargeAmount", charge * 100f, soundID); + base.characterBody.SetSpreadBloom(charge); + base.characterBody.SetAimTimer(3f); + if (charge >= minChargeForChargedAttack && !chargeVfxInstanceTransform && (bool)chargeVfxPrefab) + { + if ((bool)crosshairOverridePrefab && crosshairOverrideRequest == null) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + Transform transform = FindModelChild(chargeVfxChildLocatorName); + if ((bool)transform) + { + chargeVfxInstanceTransform = UnityEngine.Object.Instantiate(chargeVfxPrefab, transform).transform; + ScaleParticleSystemDuration component = chargeVfxInstanceTransform.GetComponent(); + if ((bool)component) + { + component.newDuration = (1f - minChargeForChargedAttack) * chargeDuration; + } + } + PlayCrossfade("Gesture, Additive", ChargePunchIntroStateHash, ChargePunchIntroParamHash, chargeDuration, 0.1f); + PlayCrossfade("Gesture, Override", ChargePunchIntroStateHash, ChargePunchIntroParamHash, chargeDuration, 0.1f); + } + if ((bool)chargeVfxInstanceTransform) + { + base.characterMotor.walkSpeedPenaltyCoefficient = walkSpeedCoefficient; + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + public override void Update() + { + base.Update(); + Mathf.Clamp01(base.age / chargeDuration); + } + + private void AuthorityFixedUpdate() + { + if (!ShouldKeepChargingAuthority()) + { + outer.SetNextState(GetNextStateAuthority()); + } + } + + protected virtual bool ShouldKeepChargingAuthority() + { + return IsKeyDownAuthority(); + } + + protected virtual EntityState GetNextStateAuthority() + { + return new SwingChargedFist + { + charge = charge + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/BaseSwingChargedFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/BaseSwingChargedFist.cs new file mode 100644 index 0000000..020eb1e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/BaseSwingChargedFist.cs @@ -0,0 +1,122 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.Loader; + +public class BaseSwingChargedFist : LoaderMeleeAttack +{ + public float charge; + + [SerializeField] + public float minLungeSpeed; + + [SerializeField] + public float maxLungeSpeed; + + [SerializeField] + public float minPunchForce; + + [SerializeField] + public float maxPunchForce; + + [SerializeField] + public float minDuration; + + [SerializeField] + public float maxDuration; + + public static bool disableAirControlUntilCollision; + + public static float speedCoefficientOnExit; + + public static float velocityDamageCoefficient; + + protected Vector3 punchVelocity; + + private float bonusDamage; + + private static int ChargePunchStateHash = Animator.StringToHash("ChargePunch"); + + private static int ChargePunchParamHash = Animator.StringToHash("ChargePunch.playbackRate"); + + public float punchSpeed { get; private set; } + + public static event Action onHitAuthorityGlobal; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.disableAirControlUntilCollision |= disableAirControlUntilCollision; + punchVelocity = CalculateLungeVelocity(base.characterMotor.velocity, GetAimRay().direction, charge, minLungeSpeed, maxLungeSpeed); + base.characterMotor.velocity = punchVelocity; + base.characterDirection.forward = base.characterMotor.velocity.normalized; + punchSpeed = base.characterMotor.velocity.magnitude; + bonusDamage = punchSpeed * (velocityDamageCoefficient * damageStat); + } + } + + protected override float CalcDuration() + { + return Mathf.Lerp(minDuration, maxDuration, charge); + } + + protected override void PlayAnimation() + { + base.PlayAnimation(); + PlayAnimation("FullBody, Override", ChargePunchStateHash, ChargePunchParamHash, duration); + } + + protected override void AuthorityFixedUpdate() + { + base.AuthorityFixedUpdate(); + if (!base.authorityInHitPause) + { + base.characterMotor.velocity = punchVelocity; + base.characterDirection.forward = punchVelocity; + base.characterBody.isSprinting = true; + } + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + overlapAttack.damage = damageCoefficient * damageStat + bonusDamage; + overlapAttack.forceVector = base.characterMotor.velocity + GetAimRay().direction * Mathf.Lerp(minPunchForce, maxPunchForce, charge); + if (base.fixedAge + GetDeltaTime() >= duration) + { + HitBoxGroup hitBoxGroup = FindHitBoxGroup("PunchLollypop"); + if ((bool)hitBoxGroup) + { + base.hitBoxGroup = hitBoxGroup; + overlapAttack.hitBoxGroup = hitBoxGroup; + } + } + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + BaseSwingChargedFist.onHitAuthorityGlobal?.Invoke(this); + } + + public override void OnExit() + { + base.OnExit(); + base.characterMotor.velocity *= speedCoefficientOnExit; + } + + public static Vector3 CalculateLungeVelocity(Vector3 currentVelocity, Vector3 aimDirection, float charge, float minLungeSpeed, float maxLungeSpeed) + { + currentVelocity = ((Vector3.Dot(currentVelocity, aimDirection) < 0f) ? Vector3.zero : Vector3.Project(currentVelocity, aimDirection)); + return currentVelocity + aimDirection * Mathf.Lerp(minLungeSpeed, maxLungeSpeed, charge); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/BeginOvercharge.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/BeginOvercharge.cs new file mode 100644 index 0000000..ac2890a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/BeginOvercharge.cs @@ -0,0 +1,16 @@ +using RoR2; + +namespace EntityStates.Loader; + +public class BeginOvercharge : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + GetComponent().ConsumeChargeAuthority(); + } + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/BigPunch.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/BigPunch.cs new file mode 100644 index 0000000..7909e2b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/BigPunch.cs @@ -0,0 +1,123 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Orbs; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Loader; + +public class BigPunch : LoaderMeleeAttack +{ + public static int maxShockCount; + + public static float maxShockFOV; + + public static float maxShockDistance; + + public static float shockDamageCoefficient; + + public static float shockProcCoefficient; + + public static float knockbackForce; + + public static float shorthopVelocityOnEnter; + + private bool hasHit; + + private bool hasKnockbackedSelf; + + private static int BigPunchStateHash = Animator.StringToHash("BigPunch"); + + private static int BigPunchParamHash = Animator.StringToHash("BigPunch.playbackRate"); + + private Vector3 punchVector => base.characterDirection.forward.normalized; + + public override void OnEnter() + { + base.OnEnter(); + base.characterMotor.velocity.y = shorthopVelocityOnEnter; + } + + protected override void PlayAnimation() + { + base.PlayAnimation(); + PlayAnimation("FullBody, Override", BigPunchStateHash, BigPunchParamHash, duration); + } + + protected override void AuthorityFixedUpdate() + { + base.AuthorityFixedUpdate(); + if (hasHit && !hasKnockbackedSelf && !base.authorityInHitPause) + { + hasKnockbackedSelf = true; + base.healthComponent.TakeDamageForce(punchVector * (0f - knockbackForce), alwaysApply: true); + } + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + overlapAttack.maximumOverlapTargets = 1; + } + + protected override void OnMeleeHitAuthority() + { + if (!hasHit) + { + base.OnMeleeHitAuthority(); + hasHit = true; + if ((bool)FindModelChild(swingEffectMuzzleString)) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = GetAimRay().origin; + fireProjectileInfo.rotation = Quaternion.LookRotation(punchVector); + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.damage = 1f * damageStat; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.projectilePrefab = LegacyResourcesAPI.Load("Prefabs/Projectiles/LoaderZapCone"); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + } + + private void FireSecondaryRaysServer() + { + Ray aimRay = GetAimRay(); + TeamIndex team = GetTeam(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(team); + bullseyeSearch.maxAngleFilter = maxShockFOV * 0.5f; + bullseyeSearch.maxDistanceFilter = maxShockDistance; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = punchVector; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.RefreshCandidates(); + List list = bullseyeSearch.GetResults().Where(Util.IsValid).ToList(); + Transform transform = FindModelChild(swingEffectMuzzleString); + if (!transform) + { + return; + } + for (int i = 0; i < Mathf.Min(list.Count, maxShockCount); i++) + { + HurtBox hurtBox = list[i]; + if ((bool)hurtBox) + { + LightningOrb lightningOrb = new LightningOrb(); + lightningOrb.bouncedObjects = new List(); + lightningOrb.attacker = base.gameObject; + lightningOrb.teamIndex = team; + lightningOrb.damageValue = damageStat * shockDamageCoefficient; + lightningOrb.isCrit = RollCrit(); + lightningOrb.origin = transform.position; + lightningOrb.bouncesRemaining = 0; + lightningOrb.lightningType = LightningOrb.LightningType.Loader; + lightningOrb.procCoefficient = shockProcCoefficient; + lightningOrb.target = hurtBox; + OrbManager.instance.AddOrb(lightningOrb); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/ChargeFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/ChargeFist.cs new file mode 100644 index 0000000..d02ac84 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/ChargeFist.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Loader; + +public class ChargeFist : BaseChargeFist +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/ChargeZapFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/ChargeZapFist.cs new file mode 100644 index 0000000..0e8a219 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/ChargeZapFist.cs @@ -0,0 +1,17 @@ +namespace EntityStates.Loader; + +public class ChargeZapFist : BaseChargeFist +{ + protected override bool ShouldKeepChargingAuthority() + { + return base.fixedAge < base.chargeDuration; + } + + protected override EntityState GetNextStateAuthority() + { + return new SwingZapFist + { + charge = base.charge + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/FireHook.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/FireHook.cs new file mode 100644 index 0000000..5db7305 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/FireHook.cs @@ -0,0 +1,94 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Loader; + +public class FireHook : BaseSkillState +{ + [SerializeField] + public GameObject projectilePrefab; + + public static float damageCoefficient; + + public static GameObject muzzleflashEffectPrefab; + + public static string fireSoundString; + + public GameObject hookInstance; + + protected ProjectileStickOnImpact hookStickOnImpact; + + private bool isStuck; + + private bool hadHookInstance; + + private uint soundID; + + private static int FireHookIntroStateHash = Animator.StringToHash("FireHookIntro"); + + private static int FireHookLoopStateHash = Animator.StringToHash("FireHookLoop"); + + private static int FireHookExitStateHash = Animator.StringToHash("FireHookExit"); + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Quaternion.LookRotation(ray.direction); + fireProjectileInfo.crit = base.characterBody.RollCrit(); + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = 0f; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.owner = base.gameObject; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, "MuzzleLeft", transmit: false); + Util.PlaySound(fireSoundString, base.gameObject); + PlayAnimation("Grapple", FireHookIntroStateHash); + } + + public void SetHookReference(GameObject hook) + { + hookInstance = hook; + hookStickOnImpact = hook.GetComponent(); + hadHookInstance = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)hookStickOnImpact) + { + if (hookStickOnImpact.stuck && !isStuck) + { + PlayAnimation("Grapple", FireHookLoopStateHash); + } + isStuck = hookStickOnImpact.stuck; + } + if (base.isAuthority && !hookInstance && hadHookInstance) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + PlayAnimation("Grapple", FireHookExitStateHash); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, "MuzzleLeft", transmit: false); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/FireYankHook.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/FireYankHook.cs new file mode 100644 index 0000000..77b62e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/FireYankHook.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Loader; + +public class FireYankHook : FireHook +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/GroundSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/GroundSlam.cs new file mode 100644 index 0000000..a61a764 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/GroundSlam.cs @@ -0,0 +1,123 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Loader; + +public class GroundSlam : BaseCharacterMain +{ + public static float airControl; + + public static float minimumDuration; + + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastDamageCoefficient; + + public static float blastForce; + + public static string enterSoundString; + + public static float initialVerticalVelocity; + + public static float exitVerticalVelocity; + + public static float verticalAcceleration; + + public static float exitSlowdownCoefficient; + + public static Vector3 blastBonusForce; + + public static GameObject blastImpactEffectPrefab; + + public static GameObject blastEffectPrefab; + + public static GameObject fistEffectPrefab; + + private float previousAirControl; + + private GameObject leftFistEffectInstance; + + private GameObject rightFistEffectInstance; + + private bool detonateNextFrame; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "GroundSlam", 0.2f); + if (base.isAuthority) + { + base.characterMotor.onMovementHit += OnMovementHit; + base.characterMotor.velocity.y = initialVerticalVelocity; + } + Util.PlaySound(enterSoundString, base.gameObject); + previousAirControl = base.characterMotor.airControl; + base.characterMotor.airControl = airControl; + leftFistEffectInstance = Object.Instantiate(fistEffectPrefab, FindModelChild("MechHandR")); + rightFistEffectInstance = Object.Instantiate(fistEffectPrefab, FindModelChild("MechHandL")); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)base.characterMotor) + { + base.characterMotor.moveDirection = base.inputBank.moveVector; + base.characterDirection.moveVector = base.characterMotor.moveDirection; + base.characterMotor.velocity.y += verticalAcceleration * GetDeltaTime(); + if (base.fixedAge >= minimumDuration && (detonateNextFrame || base.characterMotor.Motor.GroundingStatus.IsStableOnGround)) + { + DetonateAuthority(); + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + if (base.isAuthority) + { + base.characterMotor.onMovementHit -= OnMovementHit; + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.velocity *= exitSlowdownCoefficient; + base.characterMotor.velocity.y = exitVerticalVelocity; + } + base.characterMotor.airControl = previousAirControl; + EntityState.Destroy(leftFistEffectInstance); + EntityState.Destroy(rightFistEffectInstance); + base.OnExit(); + } + + private void OnMovementHit(ref CharacterMotor.MovementHitInfo movementHitInfo) + { + detonateNextFrame = true; + } + + protected BlastAttack.Result DetonateAuthority() + { + Vector3 footPosition = base.characterBody.footPosition; + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = footPosition, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + damageType = DamageType.Stun1s, + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = footPosition, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/LoaderMeleeAttack.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/LoaderMeleeAttack.cs new file mode 100644 index 0000000..76e1286 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/LoaderMeleeAttack.cs @@ -0,0 +1,28 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Loader; + +public class LoaderMeleeAttack : BasicMeleeAttack +{ + public static GameObject overchargeImpactEffectPrefab; + + public static float barrierPercentagePerHit; + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + if (HasBuff(JunkContent.Buffs.LoaderOvercharged)) + { + overlapAttack.damage *= 2f; + overlapAttack.hitEffectPrefab = overchargeImpactEffectPrefab; + overlapAttack.damageType |= (DamageTypeCombo)DamageType.Stun1s; + } + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + base.healthComponent.AddBarrierAuthority(barrierPercentagePerHit * base.healthComponent.fullBarrier); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/PreGroundSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/PreGroundSlam.cs new file mode 100644 index 0000000..23e9605 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/PreGroundSlam.cs @@ -0,0 +1,40 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Loader; + +public class PreGroundSlam : BaseCharacterMain +{ + public static float baseDuration; + + public static string enterSoundString; + + public static float upwardVelocity; + + private float duration; + + private static int PreGroundSlamStateHash = Animator.StringToHash("PreGroundSlam"); + + private static int GroundSlamParamHash = Animator.StringToHash("GroundSlam.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Body", PreGroundSlamStateHash, GroundSlamParamHash, duration); + Util.PlaySound(enterSoundString, base.gameObject); + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.disableAirControlUntilCollision = false; + base.characterMotor.velocity.y = upwardVelocity; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterMotor.moveDirection = base.inputBank.moveVector; + if (base.fixedAge > duration) + { + outer.SetNextState(new GroundSlam()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingChargedFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingChargedFist.cs new file mode 100644 index 0000000..db8f018 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingChargedFist.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Loader; + +public class SwingChargedFist : BaseSwingChargedFist +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingComboFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingComboFist.cs new file mode 100644 index 0000000..fe1d261 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingComboFist.cs @@ -0,0 +1,46 @@ +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Loader; + +public class SwingComboFist : LoaderMeleeAttack, SteppedSkillDef.IStepSetter +{ + public int gauntlet; + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + gauntlet = i; + } + + protected override void PlayAnimation() + { + string animationStateName = ((gauntlet == 0) ? "SwingFistRight" : "SwingFistLeft"); + float num = Mathf.Max(duration, 0.2f); + PlayCrossfade("Gesture, Additive", animationStateName, "SwingFist.playbackRate", num, 0.1f); + PlayCrossfade("Gesture, Override", animationStateName, "SwingFist.playbackRate", num, 0.1f); + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectMuzzleString = ((gauntlet == 0) ? "SwingRight" : "SwingLeft"); + base.BeginMeleeAttackEffect(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)gauntlet); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + gauntlet = reader.ReadByte(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingZapFist.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingZapFist.cs new file mode 100644 index 0000000..7140634 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/SwingZapFist.cs @@ -0,0 +1,54 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Loader; + +public class SwingZapFist : BaseSwingChargedFist +{ + public static float selfKnockback; + + private bool hasHit; + + protected override void OnMeleeHitAuthority() + { + if (!hasHit) + { + base.OnMeleeHitAuthority(); + hasHit = true; + if ((bool)FindModelChild(swingEffectMuzzleString)) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = FindModelChild(swingEffectMuzzleString).position; + fireProjectileInfo.rotation = Quaternion.LookRotation(punchVelocity); + fireProjectileInfo.crit = base.isCritAuthority; + fireProjectileInfo.damage = 1f * damageStat; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.projectilePrefab = LegacyResourcesAPI.Load("Prefabs/Projectiles/LoaderZapCone"); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + } + + protected override void AuthorityExitHitPause() + { + base.AuthorityExitHitPause(); + outer.SetNextStateToMain(); + } + + public override void OnExit() + { + base.OnExit(); + if (base.isAuthority && hasHit && (bool)base.healthComponent) + { + Vector3 vector = punchVelocity; + vector.y = Mathf.Min(vector.y, 0f); + vector = vector.normalized; + vector *= 0f - selfKnockback; + if ((bool)base.characterMotor) + { + base.characterMotor.ApplyForce(vector, alwaysApply: true); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Loader/ThrowPylon.cs b/ilspy_dump/ror2_csproj/EntityStates.Loader/ThrowPylon.cs new file mode 100644 index 0000000..c85b870 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Loader/ThrowPylon.cs @@ -0,0 +1,61 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Loader; + +public class ThrowPylon : BaseState +{ + public static GameObject projectilePrefab; + + public static float baseDuration; + + public static float damageCoefficient; + + public static string muzzleString; + + public static GameObject muzzleflashObject; + + public static string soundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.force = 0f; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.position = aimRay.origin; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.rotation = Quaternion.LookRotation(aimRay.direction); + fireProjectileInfo.target = null; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + EffectManager.SimpleMuzzleFlash(muzzleflashObject, base.gameObject, muzzleString, transmit: false); + Util.PlaySound(soundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && duration <= base.age) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LockedMage/UnlockingMage.cs b/ilspy_dump/ror2_csproj/EntityStates.LockedMage/UnlockingMage.cs new file mode 100644 index 0000000..4e61d35 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LockedMage/UnlockingMage.cs @@ -0,0 +1,56 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LockedMage; + +public class UnlockingMage : BaseState +{ + public static GameObject unlockingMageChargeEffectPrefab; + + public static GameObject unlockingMageExplosionEffectPrefab; + + public static float unlockingDuration; + + public static string unlockingChargeSFXString; + + public static float unlockingChargeSFXStringPitch; + + public static string unlockingExplosionSFXString; + + public static float unlockingExplosionSFXStringPitch; + + private bool unlocked; + + public static event Action onOpened; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleEffect(unlockingMageChargeEffectPrefab, base.transform.position, Util.QuaternionSafeLookRotation(Vector3.up), transmit: false); + Util.PlayAttackSpeedSound(unlockingChargeSFXString, base.gameObject, unlockingChargeSFXStringPitch); + GetModelTransform().GetComponent().FindChild("Suspension").gameObject.SetActive(value: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!(base.fixedAge >= unlockingDuration) || unlocked) + { + return; + } + base.gameObject.SetActive(value: false); + EffectManager.SimpleEffect(unlockingMageExplosionEffectPrefab, base.transform.position, Util.QuaternionSafeLookRotation(Vector3.up), transmit: false); + Util.PlayAttackSpeedSound(unlockingExplosionSFXString, base.gameObject, unlockingExplosionSFXStringPitch); + unlocked = true; + if (NetworkServer.active) + { + PurchaseInteraction component = GetComponent(); + if ((bool)component && (bool)component.lastActivator) + { + UnlockingMage.onOpened?.Invoke(component.lastActivator); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster.Weapon/FireExploderShards.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster.Weapon/FireExploderShards.cs new file mode 100644 index 0000000..12d03c5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster.Weapon/FireExploderShards.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +namespace EntityStates.LunarExploderMonster.Weapon; + +public class FireExploderShards : GenericProjectileBaseState +{ + private static int FireExploderShardsStateHash = Animator.StringToHash("FireExploderShards"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Gesture, Additive", FireExploderShardsStateHash); + base.characterBody.SetAimTimer(0f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster/DeathState.cs new file mode 100644 index 0000000..338f8f4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster/DeathState.cs @@ -0,0 +1,132 @@ +using System.Collections; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LunarExploderMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathPreExplosionVFX; + + public static GameObject deathExplosionEffect; + + public static GameObject projectilePrefab; + + public static float projectileVerticalSpawnOffset; + + public static float projectileDamageCoefficient; + + public static int projectileCount; + + public static float duration; + + public static float deathExplosionRadius; + + public static string muzzleName; + + private GameObject deathPreExplosionInstance; + + private Transform muzzleTransform; + + private bool hasExploded; + + private Vector3? explosionPosition; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayCrossfade("Body", "Death", "Death.playbackRate", duration, 0.1f); + } + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + if (!muzzleTransform) + { + return; + } + explosionPosition = muzzleTransform.position; + if ((bool)deathPreExplosionVFX) + { + deathPreExplosionInstance = Object.Instantiate(deathPreExplosionVFX, muzzleTransform.position, muzzleTransform.rotation); + deathPreExplosionInstance.transform.parent = muzzleTransform; + deathPreExplosionInstance.transform.localScale = Vector3.one * deathExplosionRadius; + ScaleParticleSystemDuration component = deathPreExplosionInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)muzzleTransform) + { + explosionPosition = muzzleTransform.position; + } + if (base.fixedAge >= duration && !hasExploded) + { + if (base.isAuthority) + { + FireExplosion(); + } + base.modelLocator?.modelTransform?.gameObject.SetActive(value: false); + ProjectileDotZone projectileDotZone = projectilePrefab?.GetComponent(); + if ((bool)projectileDotZone) + { + base.modelLocator?.StartCoroutine(DoDestroyAfrerProjectileDestroyed(projectileDotZone.lifetime + 0.5f)); + } + hasExploded = true; + } + } + + private IEnumerator DoDestroyAfrerProjectileDestroyed(float delay) + { + yield return new WaitForSeconds(delay); + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } + + private void FireExplosion() + { + if (!hasExploded && (bool)base.cachedModelTransform && base.isAuthority) + { + for (int i = 0; i < projectileCount; i++) + { + float num = 360f / (float)projectileCount; + Vector3 forward = Util.QuaternionSafeLookRotation(base.cachedModelTransform.forward, base.cachedModelTransform.up) * Util.ApplySpread(Vector3.forward, 0f, 0f, 1f, 1f, num * (float)i); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = base.characterBody.corePosition + Vector3.up * projectileVerticalSpawnOffset; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(forward); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * projectileDamageCoefficient; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + if ((bool)deathExplosionEffect) + { + EffectManager.SpawnEffect(deathExplosionEffect, new EffectData + { + origin = base.characterBody.corePosition, + scale = deathExplosionRadius + }, transmit: true); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster/SpawnState.cs new file mode 100644 index 0000000..fd6c9d1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarExploderMonster/SpawnState.cs @@ -0,0 +1,20 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarExploderMonster; + +public class SpawnState : GenericCharacterSpawnState +{ + public static GameObject spawnEffectPrefab; + + public static string spawnEffectChildString; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnEffectChildString, transmit: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/ChargeTwinShot.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/ChargeTwinShot.cs new file mode 100644 index 0000000..0c7d11c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/ChargeTwinShot.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarGolem; + +public class ChargeTwinShot : BaseState +{ + public static float baseDuration = 3f; + + public static float laserMaxWidth = 0.2f; + + public static GameObject effectPrefab; + + public static string chargeSoundString; + + private float duration; + + private uint chargePlayID; + + private List chargeEffects = new List(); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + chargePlayID = Util.PlayAttackSpeedSound(chargeSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("Gesture, Additive", "ChargeTwinShot", "TwinShot.playbackRate", duration, 0.1f); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + List list = new List(); + list.Add(component.FindChild("MuzzleLT")); + list.Add(component.FindChild("MuzzleLB")); + list.Add(component.FindChild("MuzzleRT")); + list.Add(component.FindChild("MuzzleRB")); + if ((bool)effectPrefab) + { + for (int i = 0; i < list.Count; i++) + { + if ((bool)list[i]) + { + GameObject gameObject = Object.Instantiate(effectPrefab, list[i].position, list[i].rotation); + gameObject.transform.parent = list[i]; + ScaleParticleSystemDuration component2 = gameObject.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + chargeEffects.Add(gameObject); + } + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(chargePlayID); + base.OnExit(); + for (int i = 0; i < chargeEffects.Count; i++) + { + if ((bool)chargeEffects[i]) + { + EntityState.Destroy(chargeEffects[i]); + } + } + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireTwinShots nextState = new FireTwinShots(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/DeathState.cs new file mode 100644 index 0000000..4de7853 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/DeathState.cs @@ -0,0 +1,23 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarGolem; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathExplosionEffect; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)deathExplosionEffect) + { + EffectManager.SimpleMuzzleFlash(deathExplosionEffect, base.gameObject, "Center", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/FireTwinShots.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/FireTwinShots.cs new file mode 100644 index 0000000..bb4b05c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/FireTwinShots.cs @@ -0,0 +1,210 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LunarGolem; + +public class FireTwinShots : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static GameObject dustEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float blastRadius; + + public static float force; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public static float aimTime = 2f; + + public static string leftMuzzleTop; + + public static string rightMuzzleTop; + + public static string leftMuzzleBot; + + public static string rightMuzzleBot; + + public static int refireCount = 6; + + public static float baseAimDelay = 0.1f; + + public static float minLeadTime = 2f; + + public static float maxLeadTime = 2f; + + public static float fireSoundPlaybackRate; + + public static bool useSeriesFire = true; + + private int refireIndex; + + private Ray initialAimRay; + + private bool fired; + + private float aimDelay; + + private float duration; + + private static int FireTwinShotStateHash = Animator.StringToHash("FireTwinShot"); + + private static int BufferEmptyShotStateHash = Animator.StringToHash("BufferEmpty"); + + private static int FireTwinShotParamHash = Animator.StringToHash("FireTwinShot.playbackRate"); + + private static int FireRightShotStateHash = Animator.StringToHash("FireRightShot"); + + private static int FireLeftShotStateHash = Animator.StringToHash("FireLeftShot"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + aimDelay = baseAimDelay / attackSpeedStat; + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(aimTime); + } + if (!useSeriesFire) + { + PlayAnimation("Gesture, Additive", FireTwinShotStateHash, FireTwinShotParamHash, duration); + } + else + { + PlayAnimation("Gesture, Additive", BufferEmptyShotStateHash); + } + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, fireSoundPlaybackRate); + initialAimRay = GetAimRay(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!fired && aimDelay <= base.fixedAge) + { + fired = true; + if (base.isAuthority) + { + Fire(); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + if (refireIndex < refireCount) + { + outer.SetNextState(new FireTwinShots + { + refireIndex = refireIndex + 1 + }); + } + else + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.WritePackedUInt32((uint)refireIndex); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + refireIndex = (int)reader.ReadPackedUInt32(); + } + + private void Fire() + { + Ray aimRay = GetAimRay(); + Quaternion a = Quaternion.LookRotation(initialAimRay.direction); + Quaternion b = Quaternion.LookRotation(aimRay.direction); + float num = Util.Remap(Util.Remap(refireIndex, 0f, refireCount - 1, 0f, 1f), 0f, 1f, minLeadTime, maxLeadTime) / aimDelay; + Quaternion quaternion = Quaternion.SlerpUnclamped(a, b, 1f + num); + Ray ray = new Ray(aimRay.origin, quaternion * Vector3.forward); + if (refireIndex == 0 && (bool)dustEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(dustEffectPrefab, base.gameObject, "Root", transmit: true); + } + int num2 = refireIndex; + if (!useSeriesFire) + { + num2 = refireIndex + 3; + } + while (refireIndex <= num2) + { + string muzzleName = ""; + bool flipProjectile = false; + switch (refireIndex % 4) + { + case 0: + muzzleName = rightMuzzleTop; + PlayAnimation("Gesture, Right Additive", FireRightShotStateHash); + flipProjectile = true; + break; + case 1: + muzzleName = leftMuzzleTop; + PlayAnimation("Gesture, Left Additive", FireLeftShotStateHash); + break; + case 2: + muzzleName = rightMuzzleBot; + PlayAnimation("Gesture, Right Additive", FireRightShotStateHash); + flipProjectile = true; + break; + case 3: + muzzleName = leftMuzzleBot; + PlayAnimation("Gesture, Left Additive", FireLeftShotStateHash); + break; + } + FireSingle(muzzleName, ray.direction, flipProjectile); + refireIndex++; + } + refireIndex--; + } + + private void FireSingle(string muzzleName, Vector3 aimDirection, bool flipProjectile) + { + ChildLocator modelChildLocator = GetModelChildLocator(); + if (!modelChildLocator) + { + return; + } + Transform transform = modelChildLocator.FindChild(muzzleName); + if ((bool)transform) + { + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: true); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, transform.position, Util.QuaternionSafeLookRotation(aimDirection, (!flipProjectile) ? Vector3.up : Vector3.down), base.gameObject, damageStat * damageCoefficient, force, RollCrit()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/Shell.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/Shell.cs new file mode 100644 index 0000000..a38853d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/Shell.cs @@ -0,0 +1,52 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarGolem; + +public class Shell : BaseState +{ + public static float baseDuration; + + public static float buffDuration; + + public static float preShieldAnimDuration; + + public static GameObject preShieldEffect; + + public static string preShieldSoundString; + + public static string shieldActivateSoundString; + + private bool readyToActivate; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(preShieldSoundString, base.gameObject); + PlayCrossfade("Gesture, Additive", "PreShield", 0.2f); + EffectManager.SimpleMuzzleFlash(preShieldEffect, base.gameObject, "Center", transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= preShieldAnimDuration && !readyToActivate) + { + readyToActivate = true; + Util.PlaySound(shieldActivateSoundString, base.gameObject); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.LunarShell, buffDuration); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/SpawnState.cs new file mode 100644 index 0000000..50fd333 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarGolem/SpawnState.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarGolem; + +public class SpawnState : BaseState +{ + public static float duration = 1.333f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/Active.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/Active.cs new file mode 100644 index 0000000..20348fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/Active.cs @@ -0,0 +1,22 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LunarTeleporter; + +public class Active : LunarTeleporterBaseState +{ + private static int ActiveStateHash = Animator.StringToHash("Active"); + + public override void OnEnter() + { + base.OnEnter(); + preferredInteractability = Interactability.Available; + PlayAnimation("Base", ActiveStateHash); + outer.mainStateType = new SerializableEntityStateType(typeof(ActiveToIdle)); + if (NetworkServer.active) + { + teleporterInteraction.sceneExitController.useRunNextStageScene = false; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/ActiveToIdle.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/ActiveToIdle.cs new file mode 100644 index 0000000..9420cfe --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/ActiveToIdle.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarTeleporter; + +public class ActiveToIdle : LunarTeleporterBaseState +{ + public static float duration; + + private static int ActiveToIdleStateHash = Animator.StringToHash("ActiveToIdle"); + + private static int playbackRateParamHash = Animator.StringToHash("playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", ActiveToIdleStateHash, playbackRateParamHash, duration); + preferredInteractability = Interactability.Disabled; + Util.PlaySound("Play_boss_spawn_rumble", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new Idle()); + } + } + + public override void OnExit() + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "LUNAR_TELEPORTER_IDLE" + }); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/Idle.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/Idle.cs new file mode 100644 index 0000000..556b177 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/Idle.cs @@ -0,0 +1,22 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LunarTeleporter; + +public class Idle : LunarTeleporterBaseState +{ + private static int IdleStateHash = Animator.StringToHash("Idle"); + + public override void OnEnter() + { + base.OnEnter(); + preferredInteractability = Interactability.Available; + PlayAnimation("Base", IdleStateHash); + outer.mainStateType = new SerializableEntityStateType(typeof(IdleToActive)); + if (NetworkServer.active) + { + teleporterInteraction.sceneExitController.useRunNextStageScene = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/IdleToActive.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/IdleToActive.cs new file mode 100644 index 0000000..2355707 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/IdleToActive.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarTeleporter; + +public class IdleToActive : LunarTeleporterBaseState +{ + public static float duration; + + private static int IdleToActiveStateHash = Animator.StringToHash("IdleToActive"); + + private static int playbackRateParamHash = Animator.StringToHash("playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", IdleToActiveStateHash, playbackRateParamHash, duration); + preferredInteractability = Interactability.Disabled; + Util.PlaySound("Play_boss_spawn_rumble", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new Active()); + } + } + + public override void OnExit() + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "LUNAR_TELEPORTER_ACTIVE" + }); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/LunarTeleporterBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/LunarTeleporterBaseState.cs new file mode 100644 index 0000000..e4c5758 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarTeleporter/LunarTeleporterBaseState.cs @@ -0,0 +1,35 @@ +using RoR2; + +namespace EntityStates.LunarTeleporter; + +public class LunarTeleporterBaseState : BaseState +{ + protected GenericInteraction genericInteraction; + + protected Interactability preferredInteractability = Interactability.Available; + + protected TeleporterInteraction teleporterInteraction; + + public override void OnEnter() + { + base.OnEnter(); + genericInteraction = GetComponent(); + teleporterInteraction = base.transform.root.GetComponent(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)TeleporterInteraction.instance) + { + if (TeleporterInteraction.instance.isIdle) + { + genericInteraction.Networkinteractability = preferredInteractability; + } + else + { + genericInteraction.Networkinteractability = Interactability.Disabled; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/ChargeLunarGuns.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/ChargeLunarGuns.cs new file mode 100644 index 0000000..0c5b4ea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/ChargeLunarGuns.cs @@ -0,0 +1,110 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarWisp; + +public class ChargeLunarGuns : BaseState +{ + public static string muzzleNameRoot; + + public static string muzzleNameOne; + + public static string muzzleNameTwo; + + public static float baseDuration; + + public static string windUpSound; + + public static GameObject chargeEffectPrefab; + + private GameObject chargeInstance; + + private GameObject chargeInstanceTwo; + + private float duration; + + public static float spinUpDuration; + + public static float chargeEffectDelay; + + private bool chargeEffectSpawned; + + private bool upToSpeed; + + private uint loopedSoundID; + + protected Transform muzzleTransformRoot; + + protected Transform muzzleTransformOne; + + protected Transform muzzleTransformTwo; + + public override void OnEnter() + { + base.OnEnter(); + duration = (baseDuration + spinUpDuration) / attackSpeedStat; + muzzleTransformRoot = FindModelChild(muzzleNameRoot); + muzzleTransformOne = FindModelChild(muzzleNameOne); + muzzleTransformTwo = FindModelChild(muzzleNameTwo); + loopedSoundID = Util.PlaySound(windUpSound, base.gameObject); + PlayCrossfade("Gesture", "MinigunSpinUp", 0.2f); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + StartAimMode(0.5f); + if (base.fixedAge >= chargeEffectDelay && !chargeEffectSpawned) + { + chargeEffectSpawned = true; + if ((bool)muzzleTransformOne && (bool)muzzleTransformTwo && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, muzzleTransformOne.position, muzzleTransformOne.rotation); + chargeInstance.transform.parent = muzzleTransformOne; + chargeInstanceTwo = Object.Instantiate(chargeEffectPrefab, muzzleTransformTwo.position, muzzleTransformTwo.rotation); + chargeInstanceTwo.transform.parent = muzzleTransformTwo; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + if (base.fixedAge >= spinUpDuration && !upToSpeed) + { + upToSpeed = true; + } + if (base.fixedAge >= duration && base.isAuthority) + { + FireLunarGuns fireLunarGuns = new FireLunarGuns(); + fireLunarGuns.muzzleTransformOne = muzzleTransformOne; + fireLunarGuns.muzzleTransformTwo = muzzleTransformTwo; + fireLunarGuns.muzzleNameOne = muzzleNameOne; + fireLunarGuns.muzzleNameTwo = muzzleNameTwo; + outer.SetNextState(fireLunarGuns); + } + } + + public override void OnExit() + { + base.OnExit(); + AkSoundEngine.StopPlayingID(loopedSoundID); + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + if ((bool)chargeInstanceTwo) + { + EntityState.Destroy(chargeInstanceTwo); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/DeathState.cs new file mode 100644 index 0000000..e9e84b7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/DeathState.cs @@ -0,0 +1,60 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.LunarWisp; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathEffectPrefab; + + public static string deathEffectMuzzleName; + + public static float velocityMagnitude; + + public static float explosionForce; + + private LunarWispFXController FXController; + + protected override bool shouldAutoDestroy => false; + + public override void OnEnter() + { + base.OnEnter(); + LunarWispFXController component = base.characterBody.GetComponent(); + if ((bool)component) + { + component.TurnOffFX(); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + RagdollController component2 = modelTransform.GetComponent(); + Rigidbody component3 = GetComponent(); + if ((bool)component2 && (bool)component3) + { + component2.BeginRagdoll(component3.velocity * velocityMagnitude); + } + ExplodeRigidbodiesOnStart component4 = modelTransform.GetComponent(); + if ((bool)component4) + { + component4.force = explosionForce; + component4.enabled = true; + } + } + if ((bool)base.modelLocator) + { + base.modelLocator.autoUpdateModelTransform = false; + } + FindModelChild("StandableSurface").gameObject.SetActive(value: false); + if (NetworkServer.active) + { + EffectData effectData = new EffectData + { + origin = FindModelChild(deathEffectMuzzleName).position + }; + EffectManager.SpawnEffect(deathEffectPrefab, effectData, transmit: true); + DestroyBodyAsapServer(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/FireLunarGuns.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/FireLunarGuns.cs new file mode 100644 index 0000000..0c04386 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/FireLunarGuns.cs @@ -0,0 +1,228 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarWisp; + +public class FireLunarGuns : BaseState +{ + public static GameObject muzzleVfxPrefab; + + public static float baseDuration; + + private float duration; + + public static float baseFireInterval; + + public static int baseBulletCount; + + public static float baseDamagePerSecondCoefficient; + + public static float baseForcePerSecond; + + public static float baseProcCoefficientPerSecond; + + public static float bulletMinSpread; + + public static float bulletMaxSpread; + + public static GameObject bulletTracerEffectPrefab; + + public static GameObject bulletHitEffectPrefab; + + public static bool bulletHitEffectNormal; + + public static float bulletMaxDistance; + + public static string fireSound; + + public static string windLoopSound; + + public static string windDownSound; + + public static string shootLoopSound; + + private uint windLoopSoundID; + + private uint shootLoopSoundID; + + private Transform muzzleTransform; + + public Transform muzzleTransformOne; + + public Transform muzzleTransformTwo; + + [SerializeField] + public string muzzleNameOne; + + [SerializeField] + public string muzzleNameTwo; + + private GameObject muzzleVFXInstanceOne; + + private GameObject muzzleVFXInstanceTwo; + + private float fireTimer; + + private float baseFireRate; + + private float baseBulletsPerSecond; + + private Run.FixedTimeStamp critEndTime; + + private Run.FixedTimeStamp lastCritCheck; + + protected ref InputBankTest.ButtonState skillButtonState => ref base.inputBank.skill1; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + muzzleTransformOne = FindModelChild(muzzleNameOne); + muzzleTransformTwo = FindModelChild(muzzleNameTwo); + if ((bool)muzzleTransformOne && (bool)muzzleTransformTwo && (bool)muzzleVfxPrefab) + { + muzzleVFXInstanceOne = Object.Instantiate(muzzleVfxPrefab, muzzleTransformOne.position, muzzleTransformOne.rotation); + muzzleVFXInstanceOne.transform.parent = muzzleTransformOne; + muzzleVFXInstanceTwo = Object.Instantiate(muzzleVfxPrefab, muzzleTransformTwo.position, muzzleTransformTwo.rotation); + muzzleVFXInstanceTwo.transform.parent = muzzleTransformTwo; + } + baseFireRate = 1f / baseFireInterval; + baseBulletsPerSecond = (float)baseBulletCount * baseFireRate; + critEndTime = Run.FixedTimeStamp.negativeInfinity; + lastCritCheck = Run.FixedTimeStamp.negativeInfinity; + windLoopSoundID = Util.PlaySound(windLoopSound, base.gameObject); + shootLoopSoundID = Util.PlaySound(shootLoopSound, base.gameObject); + } + + private void UpdateCrits() + { + if (lastCritCheck.timeSince >= 1f) + { + lastCritCheck = Run.FixedTimeStamp.now; + if (RollCrit()) + { + critEndTime = Run.FixedTimeStamp.now + 2f; + } + } + } + + public override void OnExit() + { + Util.PlaySound(windDownSound, base.gameObject); + if ((bool)muzzleVFXInstanceOne) + { + EntityState.Destroy(muzzleVFXInstanceOne.gameObject); + muzzleVFXInstanceOne = null; + } + if ((bool)muzzleVFXInstanceTwo) + { + EntityState.Destroy(muzzleVFXInstanceTwo.gameObject); + muzzleVFXInstanceTwo = null; + } + AkSoundEngine.StopPlayingID(windLoopSoundID); + AkSoundEngine.StopPlayingID(shootLoopSoundID); + PlayCrossfade("Gesture", "MinigunSpinDown", 0.2f); + base.OnExit(); + } + + private void OnFireShared() + { + Util.PlaySound(fireSound, base.gameObject); + if (base.isAuthority) + { + OnFireAuthority(); + } + } + + private void OnFireAuthority() + { + UpdateCrits(); + bool isCrit = !critEndTime.hasPassed; + float damage = baseDamagePerSecondCoefficient / baseBulletsPerSecond * damageStat; + float force = baseForcePerSecond / baseBulletsPerSecond; + float procCoefficient = baseProcCoefficientPerSecond / baseBulletsPerSecond; + StartAimMode(0.5f); + Ray aimRay = GetAimRay(); + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.bulletCount = (uint)baseBulletCount / 2u; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.origin = aimRay.origin; + bulletAttack.damage = damage; + bulletAttack.damageColorIndex = DamageColorIndex.Default; + bulletAttack.damageType = DamageType.Generic; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.maxDistance = bulletMaxDistance; + bulletAttack.force = force; + bulletAttack.hitMask = LayerIndex.CommonMasks.bullet; + bulletAttack.minSpread = bulletMinSpread; + bulletAttack.maxSpread = bulletMaxSpread; + bulletAttack.isCrit = isCrit; + bulletAttack.owner = base.gameObject; + bulletAttack.muzzleName = muzzleNameOne; + bulletAttack.smartCollision = false; + bulletAttack.procChainMask = default(ProcChainMask); + bulletAttack.procCoefficient = procCoefficient; + bulletAttack.radius = 0f; + bulletAttack.sniper = false; + bulletAttack.stopperMask = LayerIndex.CommonMasks.bullet; + bulletAttack.weapon = null; + bulletAttack.tracerEffectPrefab = bulletTracerEffectPrefab; + bulletAttack.spreadPitchScale = 1f; + bulletAttack.spreadYawScale = 1f; + bulletAttack.queryTriggerInteraction = QueryTriggerInteraction.UseGlobal; + bulletAttack.hitEffectPrefab = bulletHitEffectPrefab; + bulletAttack.HitEffectNormal = bulletHitEffectNormal; + bulletAttack.Fire(); + BulletAttack bulletAttack2 = new BulletAttack(); + bulletAttack2.bulletCount = (uint)baseBulletCount / 2u; + bulletAttack2.aimVector = aimRay.direction; + bulletAttack2.origin = aimRay.origin; + bulletAttack2.damage = damage; + bulletAttack2.damageColorIndex = DamageColorIndex.Default; + bulletAttack2.damageType = DamageType.Generic; + bulletAttack2.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack2.maxDistance = bulletMaxDistance; + bulletAttack2.force = force; + bulletAttack2.hitMask = LayerIndex.CommonMasks.bullet; + bulletAttack2.minSpread = bulletMinSpread; + bulletAttack2.maxSpread = bulletMaxSpread; + bulletAttack2.isCrit = isCrit; + bulletAttack2.owner = base.gameObject; + bulletAttack2.muzzleName = muzzleNameTwo; + bulletAttack2.smartCollision = false; + bulletAttack2.procChainMask = default(ProcChainMask); + bulletAttack2.procCoefficient = procCoefficient; + bulletAttack2.radius = 0f; + bulletAttack2.sniper = false; + bulletAttack2.stopperMask = LayerIndex.CommonMasks.bullet; + bulletAttack2.weapon = null; + bulletAttack2.tracerEffectPrefab = bulletTracerEffectPrefab; + bulletAttack2.spreadPitchScale = 1f; + bulletAttack2.spreadYawScale = 1f; + bulletAttack2.queryTriggerInteraction = QueryTriggerInteraction.UseGlobal; + bulletAttack2.hitEffectPrefab = bulletHitEffectPrefab; + bulletAttack2.HitEffectNormal = bulletHitEffectNormal; + bulletAttack2.Fire(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + float num = baseFireInterval / attackSpeedStat; + fireTimer += num; + OnFireShared(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/SeekingBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/SeekingBomb.cs new file mode 100644 index 0000000..3ed3d7e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/SeekingBomb.cs @@ -0,0 +1,115 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.LunarWisp; + +public class SeekingBomb : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargingEffectPrefab; + + public static GameObject projectilePrefab; + + public static string spinUpSoundString; + + public static string fireBombSoundString; + + public static string spinDownSoundString; + + public static float bombDamageCoefficient; + + public static float bombForce; + + public static string muzzleName; + + public float novaRadius; + + private float duration; + + public static float spinUpDuration; + + private bool upToSpeed; + + private GameObject chargeEffectInstance; + + private uint chargeLoopSoundID; + + public override void OnEnter() + { + base.OnEnter(); + duration = (baseDuration + spinUpDuration) / attackSpeedStat; + chargeLoopSoundID = Util.PlaySound(spinUpSoundString, base.gameObject); + PlayCrossfade("Gesture", "BombStart", 0.2f); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + base.OnExit(); + AkSoundEngine.StopPlayingID(chargeLoopSoundID); + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= spinUpDuration && !upToSpeed) + { + upToSpeed = true; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(muzzleName); + if ((bool)transform && (bool)chargingEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargingEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + chargeEffectInstance.GetComponent().newDuration = duration; + } + } + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + FireBomb(); + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private void FireBomb() + { + Util.PlaySound(fireBombSoundString, base.gameObject); + Ray aimRay = GetAimRay(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + aimRay.origin = component.FindChild(muzzleName).transform.position; + } + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * bombDamageCoefficient, bombForce, Util.CheckRoll(critStat, base.characterBody.master)); + } + Util.PlaySound(spinDownSoundString, base.gameObject); + PlayCrossfade("Gesture", "BombStop", 0.2f); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/SpawnState.cs new file mode 100644 index 0000000..a42907e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.LunarWisp/SpawnState.cs @@ -0,0 +1,70 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.LunarWisp; + +public class SpawnState : BaseState +{ + public static float duration; + + public static string spawnSoundString; + + public static float spawnEffectsDelay; + + private bool spawnEffectsTriggered; + + public static GameObject spawnEffectPrefab; + + public static string spawnEffectMuzzleName; + + public static float printDuration; + + private float mPrintDuration; + + private LunarWispFXController FXController; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + public override void OnEnter() + { + base.OnEnter(); + FXController = base.characterBody.GetComponent(); + FXController.TurnOffFX(); + mPrintDuration = printDuration; + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash); + PrintController component = GetModelTransform().gameObject.GetComponent(); + component.enabled = false; + component.printTime = mPrintDuration; + component.startingPrintHeight = 25f; + component.maxPrintHeight = 3.15f; + component.startingPrintBias = 4f; + component.maxPrintBias = 1.4f; + component.disableWhenFinished = true; + component.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + component.enabled = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= spawnEffectsDelay && !spawnEffectsTriggered) + { + spawnEffectsTriggered = true; + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnEffectMuzzleName, transmit: false); + if ((bool)FXController) + { + FXController.TurnOnFX(); + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/BaseChargeBombState.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/BaseChargeBombState.cs new file mode 100644 index 0000000..5bbdd55 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/BaseChargeBombState.cs @@ -0,0 +1,128 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public abstract class BaseChargeBombState : BaseSkillState +{ + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string chargeSoundString; + + [SerializeField] + public float baseDuration = 1.5f; + + [SerializeField] + public float minBloomRadius; + + [SerializeField] + public float maxBloomRadius; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public float minChargeDuration = 0.5f; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private uint loopSoundInstanceId; + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int ChargeNovaBombStateHash = Animator.StringToHash("ChargeNovaBomb"); + + private static int ChargeNovaBombParamHash = Animator.StringToHash("ChargeNovaBomb.playbackRate"); + + protected float duration { get; private set; } + + protected Animator animator { get; private set; } + + protected ChildLocator childLocator { get; private set; } + + protected GameObject chargeEffectInstance { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + animator = GetModelAnimator(); + childLocator = GetModelChildLocator(); + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild("MuzzleBetween") ?? base.characterBody.coreTransform; + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + ObjectScaleCurve component2 = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + if ((bool)component2) + { + component2.timeMax = duration; + } + } + } + PlayChargeAnimation(); + loopSoundInstanceId = Util.PlayAttackSpeedSound(chargeSoundString, base.gameObject, attackSpeedStat); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + StartAimMode(duration + 2f); + } + + public override void OnExit() + { + crosshairOverrideRequest?.Dispose(); + AkSoundEngine.StopPlayingID(loopSoundInstanceId); + if (!outer.destroying) + { + PlayAnimation("Gesture, Additive", EmptyStateHash); + } + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + protected float CalcCharge() + { + return Mathf.Clamp01(base.fixedAge / duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float charge = CalcCharge(); + if (base.isAuthority && ((!IsKeyDownAuthority() && base.fixedAge >= minChargeDuration) || base.fixedAge >= duration)) + { + BaseThrowBombState nextState = GetNextState(); + nextState.charge = charge; + outer.SetNextState(nextState); + } + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(Util.Remap(CalcCharge(), 0f, 1f, minBloomRadius, maxBloomRadius)); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected abstract BaseThrowBombState GetNextState(); + + protected virtual void PlayChargeAnimation() + { + PlayAnimation("Gesture, Additive", ChargeNovaBombStateHash, ChargeNovaBombParamHash, duration); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/BaseThrowBombState.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/BaseThrowBombState.cs new file mode 100644 index 0000000..d70dafd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/BaseThrowBombState.cs @@ -0,0 +1,107 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public abstract class BaseThrowBombState : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float minDamageCoefficient; + + [SerializeField] + public float maxDamageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public float selfForce; + + protected float duration; + + public float charge; + + private static int FireNovaBombStateHash = Animator.StringToHash("FireNovaBomb"); + + private static int FireNovaBombParamHash = Animator.StringToHash("FireNovaBomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayThrowAnimation(); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, "MuzzleLeft", transmit: false); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, "MuzzleRight", transmit: false); + } + Fire(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void Fire() + { + if (base.isAuthority) + { + Ray ray = GetAimRay(); + if (projectilePrefab != null) + { + float num = Util.Remap(charge, 0f, 1f, minDamageCoefficient, maxDamageCoefficient); + float num2 = charge * force; + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * num; + fireProjectileInfo.force = num2; + fireProjectileInfo.crit = RollCrit(); + FireProjectileInfo projectileInfo = fireProjectileInfo; + ModifyProjectile(ref projectileInfo); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, ref projectileInfo); + ProjectileManager.instance.FireProjectile(projectileInfo); + } + if ((bool)base.characterMotor) + { + base.characterMotor.ApplyForce(ray.direction * ((0f - selfForce) * charge)); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected virtual void PlayThrowAnimation() + { + PlayAnimation("Gesture, Additive", FireNovaBombStateHash, FireNovaBombParamHash, duration); + } + + protected virtual void ModifyProjectile(ref FireProjectileInfo projectileInfo) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeIcebomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeIcebomb.cs new file mode 100644 index 0000000..d13367c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeIcebomb.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Mage.Weapon; + +public class ChargeIcebomb : BaseChargeBombState +{ + protected override BaseThrowBombState GetNextState() + { + return new ThrowIcebomb(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeMeteor.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeMeteor.cs new file mode 100644 index 0000000..bd4eb55 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeMeteor.cs @@ -0,0 +1,165 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class ChargeMeteor : BaseState +{ + public static float baseChargeDuration; + + public static float baseDuration; + + public static GameObject areaIndicatorPrefab; + + public static float minMeteorRadius = 0f; + + public static float maxMeteorRadius = 10f; + + public static GameObject meteorEffect; + + public static float minDamageCoefficient; + + public static float maxDamageCoefficient; + + public static float procCoefficient; + + public static float force; + + public static GameObject muzzleflashEffect; + + private float stopwatch; + + private GameObject areaIndicatorInstance; + + private bool fireMeteor; + + private float radius; + + private float chargeDuration; + + private float duration; + + private BlastAttack blastAttack; + + private EffectData _effectData; + + private Vector3 _cachedScale = Vector3.one; + + private EffectManagerHelper _emh_areaIndicatorInstance; + + public override void Reset() + { + base.Reset(); + stopwatch = 0f; + areaIndicatorInstance = null; + fireMeteor = false; + radius = 0f; + chargeDuration = 0f; + duration = 0f; + if (blastAttack != null) + { + blastAttack.Reset(); + } + if (_effectData != null) + { + _effectData.Reset(); + } + _emh_areaIndicatorInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + chargeDuration = baseChargeDuration / attackSpeedStat; + duration = baseDuration / attackSpeedStat; + UpdateAreaIndicator(); + } + + private void UpdateAreaIndicator() + { + if ((bool)areaIndicatorInstance) + { + float maxDistance = 1000f; + if (Physics.Raycast(GetAimRay(), out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + areaIndicatorInstance.transform.position = hitInfo.point; + areaIndicatorInstance.transform.up = hitInfo.normal; + } + } + else if (!EffectManager.ShouldUsePooledEffect(areaIndicatorPrefab)) + { + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab); + } + else + { + _emh_areaIndicatorInstance = EffectManager.GetAndActivatePooledEffect(areaIndicatorPrefab, Vector3.zero, Quaternion.identity); + areaIndicatorInstance = _emh_areaIndicatorInstance.gameObject; + } + radius = Util.Remap(Mathf.Clamp01(stopwatch / chargeDuration), 0f, 1f, minMeteorRadius, maxMeteorRadius); + _cachedScale.x = radius; + _cachedScale.y = radius; + _cachedScale.z = radius; + areaIndicatorInstance.transform.localScale = _cachedScale; + } + + public override void Update() + { + base.Update(); + UpdateAreaIndicator(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if ((stopwatch >= duration || base.inputBank.skill2.justReleased) && base.isAuthority) + { + fireMeteor = true; + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "Muzzle", transmit: false); + if ((bool)areaIndicatorInstance) + { + if (fireMeteor) + { + float num = Util.Remap(Mathf.Clamp01(stopwatch / chargeDuration), 0f, 1f, minDamageCoefficient, maxDamageCoefficient); + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.origin = areaIndicatorInstance.transform.position; + _effectData.scale = radius; + EffectManager.SpawnEffect(meteorEffect, _effectData, transmit: true); + if (blastAttack == null) + { + blastAttack = new BlastAttack(); + } + blastAttack.radius = radius; + blastAttack.procCoefficient = procCoefficient; + blastAttack.position = areaIndicatorInstance.transform.position; + blastAttack.attacker = base.gameObject; + blastAttack.crit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + blastAttack.baseDamage = base.characterBody.damage * num; + blastAttack.falloffModel = BlastAttack.FalloffModel.SweetSpot; + blastAttack.baseForce = force; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(blastAttack.attacker); + blastAttack.Fire(); + } + if (_emh_areaIndicatorInstance != null && _emh_areaIndicatorInstance.OwningPool != null) + { + _emh_areaIndicatorInstance.OwningPool.ReturnObject(_emh_areaIndicatorInstance); + } + else + { + EntityState.Destroy(areaIndicatorInstance.gameObject); + } + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeNovabomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeNovabomb.cs new file mode 100644 index 0000000..789f0c2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ChargeNovabomb.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Mage.Weapon; + +public class ChargeNovabomb : BaseChargeBombState +{ + protected override BaseThrowBombState GetNextState() + { + return new ThrowNovabomb(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireFireBolt.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireFireBolt.cs new file mode 100644 index 0000000..c2380bf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireFireBolt.cs @@ -0,0 +1,181 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Mage.Weapon; + +public class FireFireBolt : BaseState, SteppedSkillDef.IStepSetter +{ + public enum Gauntlet + { + Left, + Right + } + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force = 20f; + + public static float attackSpeedAltAnimationThreshold; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float attackSoundPitch; + + public static float bloom; + + private float duration; + + private bool hasFiredGauntlet; + + private string muzzleString; + + private Transform muzzleTransform; + + private Animator animator; + + private ChildLocator childLocator; + + private Gauntlet gauntlet; + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int Cast1LeftStateHash = Animator.StringToHash("Cast1Left"); + + private static int FireGauntletLeftStateHash = Animator.StringToHash("FireGauntletLeft"); + + private static int Cast1RightStateHash = Animator.StringToHash("Cast1Right"); + + private static int FireGauntletRightStateHash = Animator.StringToHash("FireGauntletRight"); + + private static int HoldGauntletsUpStateHash = Animator.StringToHash("HoldGauntletsUp"); + + private static int FireGauntletParamHash = Animator.StringToHash("FireGauntlet.playbackRate"); + + public void SetStep(int i) + { + gauntlet = (Gauntlet)i; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSoundPitch); + base.characterBody.SetAimTimer(2f); + animator = GetModelAnimator(); + if ((bool)animator) + { + childLocator = animator.GetComponent(); + } + switch (gauntlet) + { + case Gauntlet.Left: + muzzleString = "MuzzleLeft"; + if (attackSpeedStat < attackSpeedAltAnimationThreshold) + { + PlayCrossfade("Gesture, Additive", Cast1LeftStateHash, FireGauntletParamHash, duration, 0.1f); + PlayAnimation("Gesture Left, Additive", EmptyStateHash); + PlayAnimation("Gesture Right, Additive", EmptyStateHash); + } + else + { + PlayAnimation("Gesture Left, Additive", FireGauntletLeftStateHash, FireGauntletParamHash, duration); + PlayAnimation("Gesture, Additive", HoldGauntletsUpStateHash, FireGauntletParamHash, duration); + FireGauntlet(); + } + break; + case Gauntlet.Right: + muzzleString = "MuzzleRight"; + if (attackSpeedStat < attackSpeedAltAnimationThreshold) + { + PlayCrossfade("Gesture, Additive", Cast1RightStateHash, FireGauntletParamHash, duration, 0.1f); + PlayAnimation("Gesture Left, Additive", EmptyStateHash); + PlayAnimation("Gesture Right, Additive", EmptyStateHash); + } + else + { + PlayAnimation("Gesture Right, Additive", FireGauntletRightStateHash, FireGauntletParamHash, duration); + PlayAnimation("Gesture, Additive", HoldGauntletsUpStateHash, FireGauntletParamHash, duration); + FireGauntlet(); + } + break; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireGauntlet() + { + if (!hasFiredGauntlet) + { + base.characterBody.AddSpreadBloom(bloom); + hasFiredGauntlet = true; + Ray ray = GetAimRay(); + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild(muzzleString); + } + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damageCoefficient * damageStat, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (animator.GetFloat("FireGauntlet.fire") > 0f && !hasFiredGauntlet) + { + FireGauntlet(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)gauntlet); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + gauntlet = (Gauntlet)reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireIceBolt.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireIceBolt.cs new file mode 100644 index 0000000..2a9ddcf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireIceBolt.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Mage.Weapon; + +public class FireIceBolt : FireFireBolt +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireIceOrb.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireIceOrb.cs new file mode 100644 index 0000000..bb933b0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireIceOrb.cs @@ -0,0 +1,101 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class FireIceOrb : BaseState +{ + public enum Gauntlet + { + Left, + Right + } + + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static string attackString; + + private float duration; + + private bool hasFiredGauntlet; + + private string muzzleString; + + private Animator animator; + + public Gauntlet gauntlet; + + private static int FireGauntletLeftStateHash = Animator.StringToHash("FireGauntletLeft"); + + private static int FireGauntletRightStateHash = Animator.StringToHash("FireGauntletRight"); + + private static int HoldGauntletsUpStateHash = Animator.StringToHash("HoldGauntletsUp"); + + private static int FireGauntletParamHash = Animator.StringToHash("FireGauntlet.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + switch (gauntlet) + { + case Gauntlet.Left: + muzzleString = "MuzzleLeft"; + PlayAnimation("Gesture Left, Additive", FireGauntletLeftStateHash, FireGauntletParamHash, duration); + break; + case Gauntlet.Right: + muzzleString = "MuzzleRight"; + PlayAnimation("Gesture Right, Additive", FireGauntletRightStateHash, FireGauntletParamHash, duration); + break; + } + PlayAnimation("Gesture, Additive", HoldGauntletsUpStateHash, FireGauntletParamHash, duration); + Util.PlaySound(attackString, base.gameObject); + animator = GetModelAnimator(); + base.characterBody.SetAimTimer(2f); + FireGauntlet(); + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireGauntlet() + { + hasFiredGauntlet = true; + Ray aimRay = GetAimRay(); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (animator.GetFloat("FireGauntlet.fire") > 0f && !hasFiredGauntlet) + { + FireGauntlet(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireLaserbolt.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireLaserbolt.cs new file mode 100644 index 0000000..df00930 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireLaserbolt.cs @@ -0,0 +1,128 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class FireLaserbolt : BaseState +{ + public enum Gauntlet + { + Left, + Right + } + + public static GameObject muzzleEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static GameObject impactEffectPrefab; + + public static float baseDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string attackString; + + private float duration; + + private bool hasFiredGauntlet; + + private string muzzleString; + + private Animator animator; + + public Gauntlet gauntlet; + + private static int FireGauntletLeftStateHash = Animator.StringToHash("FireGauntletLeft"); + + private static int FireGauntletRightStateHash = Animator.StringToHash("FireGauntletRight"); + + private static int HoldGauntletsUpStateHash = Animator.StringToHash("HoldGauntletsUp"); + + private static int FireGauntletParamHash = Animator.StringToHash("FireGauntlet.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + switch (gauntlet) + { + case Gauntlet.Left: + muzzleString = "MuzzleLeft"; + PlayAnimation("Gesture Left, Additive", FireGauntletLeftStateHash, FireGauntletParamHash, duration); + break; + case Gauntlet.Right: + muzzleString = "MuzzleRight"; + PlayAnimation("Gesture Right, Additive", FireGauntletRightStateHash, FireGauntletParamHash, duration); + break; + } + PlayAnimation("Gesture, Additive", HoldGauntletsUpStateHash, FireGauntletParamHash, duration); + Util.PlaySound(attackString, base.gameObject); + animator = GetModelAnimator(); + base.characterBody.SetAimTimer(2f); + FireGauntlet(); + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireGauntlet() + { + hasFiredGauntlet = true; + Ray aimRay = GetAimRay(); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleString; + bulletAttack.hitEffectPrefab = impactEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.radius = 0.1f; + bulletAttack.smartCollision = false; + bulletAttack.Fire(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (animator.GetFloat("FireGauntlet.fire") > 0f && !hasFiredGauntlet) + { + FireGauntlet(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + if (base.inputBank.skill1.down) + { + FireLaserbolt fireLaserbolt = new FireLaserbolt(); + fireLaserbolt.gauntlet = ((gauntlet == Gauntlet.Left) ? Gauntlet.Right : Gauntlet.Left); + outer.SetNextState(fireLaserbolt); + } + else + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireLightningBolt.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireLightningBolt.cs new file mode 100644 index 0000000..fcf99ea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireLightningBolt.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Mage.Weapon; + +public class FireLightningBolt : FireFireBolt +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireRoller.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireRoller.cs new file mode 100644 index 0000000..87a0aab --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/FireRoller.cs @@ -0,0 +1,289 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class FireRoller : BaseState +{ + public static GameObject fireProjectilePrefab; + + public static GameObject iceProjectilePrefab; + + public static GameObject lightningProjectilePrefab; + + public static GameObject fireMuzzleflashEffectPrefab; + + public static GameObject iceMuzzleflashEffectPrefab; + + public static GameObject lightningMuzzleflashEffectPrefab; + + public static GameObject fireAreaIndicatorPrefab; + + public static GameObject iceAreaIndicatorPrefab; + + public static GameObject lightningAreaIndicatorPrefab; + + public static string fireAttackSoundString; + + public static string iceAttackSoundString; + + public static string lightningAttackSoundString; + + public static float targetProjectileSpeed; + + public static float baseEntryDuration = 2f; + + public static float baseDuration = 2f; + + public static float baseExitDuration = 2f; + + public static float fireDamageCoefficient; + + public static float iceDamageCoefficient; + + public static float lightningDamageCoefficient; + + private float stopwatch; + + private float fireDuration; + + private float entryDuration; + + private float exitDuration; + + private bool hasFiredRoller; + + private bool hasBegunExit; + + private GameObject areaIndicatorInstance; + + private string muzzleString; + + private Transform muzzleTransform; + + private Animator animator; + + private ChildLocator childLocator; + + private GameObject areaIndicatorPrefab; + + private float damageCoefficient = 1.2f; + + private string attackString; + + private GameObject projectilePrefab; + + private GameObject muzzleflashEffectPrefab; + + private EffectManagerHelper _emh_areaIndicatorInstance; + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int EnterRollerStateHash = Animator.StringToHash("EnterRoller"); + + private static int EnterRollerParamHash = Animator.StringToHash("EnterRoller.playbackRate"); + + private static int FireRollerStateHash = Animator.StringToHash("FireRoller"); + + private static int FireRollerParamHash = Animator.StringToHash("FireRoller.playbackRate"); + + private static int ExitRollerStateHash = Animator.StringToHash("ExitRoller"); + + private static int ExitRollerParamHash = Animator.StringToHash("ExitRoller.playbackRate"); + + public override void Reset() + { + base.Reset(); + fireDuration = 0f; + entryDuration = 0f; + exitDuration = 0f; + hasFiredRoller = false; + hasBegunExit = false; + areaIndicatorInstance = null; + muzzleString = string.Empty; + muzzleTransform = null; + animator = null; + childLocator = null; + areaIndicatorPrefab = null; + damageCoefficient = 1.2f; + attackString = string.Empty; + projectilePrefab = null; + muzzleflashEffectPrefab = null; + _emh_areaIndicatorInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + InitElement(MageElement.Ice); + stopwatch = 0f; + entryDuration = baseEntryDuration / attackSpeedStat; + fireDuration = baseDuration / attackSpeedStat; + exitDuration = baseExitDuration / attackSpeedStat; + Util.PlaySound(attackString, base.gameObject); + base.characterBody.SetAimTimer(fireDuration + entryDuration + exitDuration + 2f); + animator = GetModelAnimator(); + if ((bool)animator) + { + childLocator = animator.GetComponent(); + } + muzzleString = "MuzzleRight"; + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild(muzzleString); + } + PlayAnimation("Gesture Left, Additive", EmptyStateHash); + PlayAnimation("Gesture Right, Additive", EmptyStateHash); + PlayAnimation("Gesture, Additive", EnterRollerStateHash, EnterRollerParamHash, entryDuration); + if ((bool)areaIndicatorPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(areaIndicatorPrefab)) + { + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab); + return; + } + _emh_areaIndicatorInstance = EffectManager.GetAndActivatePooledEffect(areaIndicatorPrefab, Vector3.zero, Quaternion.identity); + areaIndicatorInstance = _emh_areaIndicatorInstance.gameObject; + } + } + + private void UpdateAreaIndicator() + { + if ((bool)areaIndicatorInstance) + { + float maxDistance = 1000f; + if (Physics.Raycast(GetAimRay(), out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + areaIndicatorInstance.transform.position = hitInfo.point; + areaIndicatorInstance.transform.rotation = Util.QuaternionSafeLookRotation(base.transform.position - areaIndicatorInstance.transform.position, hitInfo.normal); + } + } + } + + public override void Update() + { + base.Update(); + UpdateAreaIndicator(); + } + + protected void DestroyAreaIndicator() + { + if (areaIndicatorInstance != null) + { + if (_emh_areaIndicatorInstance != null && _emh_areaIndicatorInstance.OwningPool != null) + { + _emh_areaIndicatorInstance.OwningPool.ReturnObject(_emh_areaIndicatorInstance); + } + else + { + EntityState.Destroy(areaIndicatorInstance); + } + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + } + } + + public override void OnExit() + { + base.OnExit(); + DestroyAreaIndicator(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= entryDuration && !hasFiredRoller) + { + PlayAnimation("Gesture, Additive", FireRollerStateHash, FireRollerParamHash, fireDuration); + FireRollerProjectile(); + DestroyAreaIndicator(); + } + if (stopwatch >= entryDuration + fireDuration && !hasBegunExit) + { + hasBegunExit = true; + PlayAnimation("Gesture, Additive", ExitRollerStateHash, ExitRollerParamHash, exitDuration); + } + if (stopwatch >= entryDuration + fireDuration + exitDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireRollerProjectile() + { + hasFiredRoller = true; + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (!base.isAuthority || !(projectilePrefab != null)) + { + return; + } + float maxDistance = 1000f; + Ray aimRay = GetAimRay(); + Vector3 forward = aimRay.direction; + Vector3 vector = aimRay.origin; + float magnitude = targetProjectileSpeed; + if ((bool)muzzleTransform) + { + vector = muzzleTransform.position; + if (Physics.Raycast(aimRay, out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + float num = magnitude; + Vector3 vector2 = hitInfo.point - vector; + Vector2 vector3 = new Vector2(vector2.x, vector2.z); + float magnitude2 = vector3.magnitude; + float y = Trajectory.CalculateInitialYSpeed(magnitude2 / num, vector2.y); + Vector3 vector4 = new Vector3(vector3.x / magnitude2 * num, y, vector3.y / magnitude2 * num); + magnitude = vector4.magnitude; + forward = vector4 / magnitude; + } + } + ProjectileManager.instance.FireProjectile(projectilePrefab, vector, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, magnitude); + } + + private void InitElement(MageElement defaultElement) + { + MageCalibrationController component = GetComponent(); + if ((bool)component) + { + MageElement activeCalibrationElement = component.GetActiveCalibrationElement(); + if (activeCalibrationElement != 0) + { + defaultElement = activeCalibrationElement; + } + } + switch (defaultElement) + { + case MageElement.Fire: + damageCoefficient = fireDamageCoefficient; + attackString = fireAttackSoundString; + projectilePrefab = fireProjectilePrefab; + muzzleflashEffectPrefab = fireMuzzleflashEffectPrefab; + areaIndicatorPrefab = fireAreaIndicatorPrefab; + break; + case MageElement.Ice: + damageCoefficient = iceDamageCoefficient; + attackString = iceAttackSoundString; + projectilePrefab = iceProjectilePrefab; + muzzleflashEffectPrefab = iceMuzzleflashEffectPrefab; + areaIndicatorPrefab = iceAreaIndicatorPrefab; + break; + case MageElement.Lightning: + damageCoefficient = lightningDamageCoefficient; + attackString = lightningAttackSoundString; + projectilePrefab = lightningProjectilePrefab; + muzzleflashEffectPrefab = lightningMuzzleflashEffectPrefab; + areaIndicatorPrefab = lightningAreaIndicatorPrefab; + break; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/Flamethrower.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/Flamethrower.cs new file mode 100644 index 0000000..1bad676 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/Flamethrower.cs @@ -0,0 +1,215 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class Flamethrower : BaseState +{ + [SerializeField] + public GameObject flamethrowerEffectPrefab; + + public static GameObject impactEffectPrefab; + + public static GameObject tracerEffectPrefab; + + [SerializeField] + public float maxDistance; + + public static float radius; + + public static float baseEntryDuration = 1f; + + public static float baseFlamethrowerDuration = 2f; + + public static float totalDamageCoefficient = 1.2f; + + public static float procCoefficientPerTick; + + public static float tickFrequency; + + public static float force = 20f; + + public static string startAttackSoundString; + + public static string endAttackSoundString; + + public static float ignitePercentChance; + + public static float recoilForce; + + private float tickDamageCoefficient; + + private float flamethrowerStopwatch; + + private float stopwatch; + + private float entryDuration; + + private float flamethrowerDuration; + + private bool hasBegunFlamethrower; + + private ChildLocator childLocator; + + private Transform leftFlamethrowerTransform; + + private Transform rightFlamethrowerTransform; + + private Transform leftMuzzleTransform; + + private Transform rightMuzzleTransform; + + private bool isCrit; + + private static int PrepFlamethrowerStateHash = Animator.StringToHash("PrepFlamethrower"); + + private static int ExitFlamethrowerStateHash = Animator.StringToHash("ExitFlamethrower"); + + private static int FlamethrowerParamHash = Animator.StringToHash("Flamethrower.playbackRate"); + + private const float flamethrowerEffectBaseDistance = 16f; + + private static int FlamethrowerStateHash = Animator.StringToHash("Flamethrower"); + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + entryDuration = baseEntryDuration / attackSpeedStat; + flamethrowerDuration = baseFlamethrowerDuration; + Transform modelTransform = GetModelTransform(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(entryDuration + flamethrowerDuration + 1f); + } + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + leftMuzzleTransform = childLocator.FindChild("MuzzleLeft"); + rightMuzzleTransform = childLocator.FindChild("MuzzleRight"); + } + int num = Mathf.CeilToInt(flamethrowerDuration * tickFrequency); + tickDamageCoefficient = totalDamageCoefficient / (float)num; + if (base.isAuthority && (bool)base.characterBody) + { + isCrit = Util.CheckRoll(critStat, base.characterBody.master); + } + PlayAnimation("Gesture, Additive", PrepFlamethrowerStateHash, FlamethrowerParamHash, entryDuration); + } + + public override void OnExit() + { + Util.PlaySound(endAttackSoundString, base.gameObject); + PlayCrossfade("Gesture, Additive", ExitFlamethrowerStateHash, 0.1f); + if ((bool)leftFlamethrowerTransform) + { + EntityState.Destroy(leftFlamethrowerTransform.gameObject); + } + if ((bool)rightFlamethrowerTransform) + { + EntityState.Destroy(rightFlamethrowerTransform.gameObject); + } + base.OnExit(); + } + + private void FireGauntlet(string muzzleString) + { + Ray aimRay = GetAimRay(); + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.damage = tickDamageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.muzzleName = muzzleString; + bulletAttack.hitEffectPrefab = impactEffectPrefab; + bulletAttack.isCrit = isCrit; + bulletAttack.radius = radius; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.stopperMask = LayerIndex.world.mask; + bulletAttack.procCoefficient = procCoefficientPerTick; + bulletAttack.maxDistance = maxDistance; + bulletAttack.smartCollision = true; + bulletAttack.damageType = (Util.CheckRoll(ignitePercentChance, base.characterBody.master) ? DamageType.IgniteOnHit : DamageType.Generic); + bulletAttack.allowTrajectoryAimAssist = false; + bulletAttack.Fire(); + if ((bool)base.characterMotor) + { + base.characterMotor.ApplyForce(aimRay.direction * (0f - recoilForce)); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= entryDuration && !hasBegunFlamethrower) + { + hasBegunFlamethrower = true; + Util.PlaySound(startAttackSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", FlamethrowerStateHash, FlamethrowerParamHash, flamethrowerDuration); + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild("MuzzleLeft"); + Transform transform2 = childLocator.FindChild("MuzzleRight"); + if ((bool)transform) + { + leftFlamethrowerTransform = Object.Instantiate(flamethrowerEffectPrefab, transform).transform; + } + if ((bool)transform2) + { + rightFlamethrowerTransform = Object.Instantiate(flamethrowerEffectPrefab, transform2).transform; + } + if ((bool)leftFlamethrowerTransform) + { + leftFlamethrowerTransform.GetComponent().newDuration = flamethrowerDuration; + } + if ((bool)rightFlamethrowerTransform) + { + rightFlamethrowerTransform.GetComponent().newDuration = flamethrowerDuration; + } + } + FireGauntlet("MuzzleCenter"); + } + if (hasBegunFlamethrower) + { + flamethrowerStopwatch += Time.deltaTime; + float num = 1f / tickFrequency / attackSpeedStat; + if (flamethrowerStopwatch > num) + { + flamethrowerStopwatch -= num; + FireGauntlet("MuzzleCenter"); + } + UpdateFlamethrowerEffect(); + } + if (stopwatch >= flamethrowerDuration + entryDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void UpdateFlamethrowerEffect() + { + Ray aimRay = GetAimRay(); + Vector3 direction = aimRay.direction; + Vector3 direction2 = aimRay.direction; + if ((bool)leftFlamethrowerTransform) + { + leftFlamethrowerTransform.forward = direction; + } + if ((bool)rightFlamethrowerTransform) + { + rightFlamethrowerTransform.forward = direction2; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/IceNova.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/IceNova.cs new file mode 100644 index 0000000..007eed8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/IceNova.cs @@ -0,0 +1,84 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class IceNova : BaseState +{ + public static GameObject impactEffectPrefab; + + public static GameObject novaEffectPrefab; + + public static float baseStartDuration; + + public static float baseEndDuration = 2f; + + public static float damageCoefficient = 1.2f; + + public static float procCoefficient; + + public static float force = 20f; + + public static float novaRadius; + + public static string attackString; + + private float stopwatch; + + private float startDuration; + + private float endDuration; + + private bool hasCastNova; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + endDuration = baseEndDuration / attackSpeedStat; + startDuration = baseStartDuration / attackSpeedStat; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= startDuration && !hasCastNova) + { + hasCastNova = true; + EffectManager.SpawnEffect(novaEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = novaRadius + }, transmit: true); + BlastAttack obj = new BlastAttack + { + radius = novaRadius, + procCoefficient = procCoefficient, + position = base.transform.position, + attacker = base.gameObject, + crit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master), + baseDamage = base.characterBody.damage * damageCoefficient, + falloffModel = BlastAttack.FalloffModel.None, + damageType = DamageType.Freeze2s, + baseForce = force + }; + obj.teamIndex = TeamComponent.GetObjectTeam(obj.attacker); + obj.Fire(); + } + if (stopwatch >= startDuration + endDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/PrepWall.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/PrepWall.cs new file mode 100644 index 0000000..13a0d45 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/PrepWall.cs @@ -0,0 +1,167 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Mage.Weapon; + +public class PrepWall : BaseState +{ + public static float baseDuration; + + public static GameObject areaIndicatorPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient; + + public static GameObject muzzleflashEffect; + + public static GameObject goodCrosshairPrefab; + + public static GameObject badCrosshairPrefab; + + public static string prepWallSoundString; + + public static float maxDistance; + + public static string fireSoundString; + + public static float maxSlopeAngle; + + private float duration; + + private float stopwatch; + + private bool goodPlacement; + + private GameObject areaIndicatorInstance; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private EffectManagerHelper _emh_areaIndicatorInstance; + + private static int PrepWallStateHash = Animator.StringToHash("PrepWall"); + + private static int PrepWallParamHash = Animator.StringToHash("PrepWall.playbackRate"); + + private static int FireWallStateHash = Animator.StringToHash("FireWall"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + stopwatch = 0f; + goodPlacement = false; + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + base.characterBody.SetAimTimer(duration + 2f); + PlayAnimation("Gesture, Additive", PrepWallStateHash, PrepWallParamHash, duration); + Util.PlaySound(prepWallSoundString, base.gameObject); + if (!EffectManager.ShouldUsePooledEffect(areaIndicatorPrefab)) + { + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab); + } + else + { + _emh_areaIndicatorInstance = EffectManager.GetAndActivatePooledEffect(areaIndicatorPrefab, Vector3.zero, Quaternion.identity); + areaIndicatorInstance = _emh_areaIndicatorInstance.gameObject; + } + UpdateAreaIndicator(); + } + + private void UpdateAreaIndicator() + { + bool flag = goodPlacement; + goodPlacement = false; + areaIndicatorInstance.SetActive(value: true); + if ((bool)areaIndicatorInstance) + { + float num = maxDistance; + float extraRaycastDistance = 0f; + Ray aimRay = GetAimRay(); + if (Physics.Raycast(CameraRigController.ModifyAimRayIfApplicable(aimRay, base.gameObject, out extraRaycastDistance), out var hitInfo, num + extraRaycastDistance, LayerIndex.world.mask)) + { + areaIndicatorInstance.transform.position = hitInfo.point; + areaIndicatorInstance.transform.up = hitInfo.normal; + areaIndicatorInstance.transform.forward = -aimRay.direction; + goodPlacement = Vector3.Angle(Vector3.up, hitInfo.normal) < maxSlopeAngle; + } + if (flag != goodPlacement || crosshairOverrideRequest == null) + { + crosshairOverrideRequest?.Dispose(); + GameObject crosshairPrefab = (goodPlacement ? goodCrosshairPrefab : badCrosshairPrefab); + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairPrefab, CrosshairUtils.OverridePriority.Skill); + } + } + areaIndicatorInstance.SetActive(goodPlacement); + } + + public override void Update() + { + base.Update(); + UpdateAreaIndicator(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && !base.inputBank.skill3.down && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + if (goodPlacement) + { + PlayAnimation("Gesture, Additive", FireWallStateHash); + Util.PlaySound(fireSoundString, base.gameObject); + if ((bool)areaIndicatorInstance && base.isAuthority) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "MuzzleLeft", transmit: true); + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "MuzzleRight", transmit: true); + Vector3 forward = areaIndicatorInstance.transform.forward; + forward.y = 0f; + forward.Normalize(); + Vector3 vector = Vector3.Cross(Vector3.up, forward); + bool crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(projectilePrefab, areaIndicatorInstance.transform.position + Vector3.up, Util.QuaternionSafeLookRotation(vector), base.gameObject, damageStat * damageCoefficient, 0f, crit); + ProjectileManager.instance.FireProjectile(projectilePrefab, areaIndicatorInstance.transform.position + Vector3.up, Util.QuaternionSafeLookRotation(-vector), base.gameObject, damageStat * damageCoefficient, 0f, crit); + } + } + else + { + base.skillLocator.utility.AddOneStock(); + PlayCrossfade("Gesture, Additive", "BufferEmpty", 0.2f); + } + } + if (_emh_areaIndicatorInstance != null && _emh_areaIndicatorInstance.OwningPool != null) + { + _emh_areaIndicatorInstance.OwningPool.ReturnObject(_emh_areaIndicatorInstance); + } + else + { + EntityState.Destroy(areaIndicatorInstance.gameObject); + } + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ThrowIcebomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ThrowIcebomb.cs new file mode 100644 index 0000000..c2f6042 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ThrowIcebomb.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Mage.Weapon; + +public class ThrowIcebomb : BaseThrowBombState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ThrowNovabomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ThrowNovabomb.cs new file mode 100644 index 0000000..6dcfb0f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage.Weapon/ThrowNovabomb.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Mage.Weapon; + +public class ThrowNovabomb : BaseThrowBombState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage/FlyUpState.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage/FlyUpState.cs new file mode 100644 index 0000000..1d814a5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage/FlyUpState.cs @@ -0,0 +1,124 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Mage; + +public class FlyUpState : MageCharacterMain +{ + public static GameObject blinkPrefab; + + public static float duration = 0.3f; + + public static string beginSoundString; + + public static string endSoundString; + + public static AnimationCurve speedCoefficientCurve; + + public static GameObject muzzleflashEffect; + + public static float blastAttackRadius; + + public static float blastAttackDamageCoefficient; + + public static float blastAttackProcCoefficient; + + public static float blastAttackForce; + + private Vector3 flyVector = Vector3.zero; + + private Transform modelTransform; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private Vector3 blastPosition; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + flyVector = Vector3.up; + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + PlayCrossfade("Body", "FlyUp", "FlyUp.playbackRate", duration, 0.1f); + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.velocity = Vector3.zero; + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "MuzzleLeft", transmit: false); + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "MuzzleRight", transmit: false); + if (base.isAuthority) + { + blastPosition = base.characterBody.corePosition; + } + if (NetworkServer.active) + { + BlastAttack obj = new BlastAttack + { + radius = blastAttackRadius, + procCoefficient = blastAttackProcCoefficient, + position = blastPosition, + attacker = base.gameObject, + crit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master), + baseDamage = base.characterBody.damage * blastAttackDamageCoefficient, + falloffModel = BlastAttack.FalloffModel.None, + baseForce = blastAttackForce + }; + obj.teamIndex = TeamComponent.GetObjectTeam(obj.attacker); + obj.damageType = DamageType.Stun1s; + obj.attackerFiltering = AttackerFiltering.NeverHitSelf; + obj.Fire(); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(blastPosition); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + blastPosition = reader.ReadVector3(); + } + + public override void HandleMovements() + { + base.HandleMovements(); + base.characterMotor.rootMotion += flyVector * (moveSpeedStat * speedCoefficientCurve.Evaluate(base.fixedAge / duration) * GetDeltaTime()); + base.characterMotor.velocity.y = 0f; + } + + protected override void UpdateAnimationParameters() + { + base.UpdateAnimationParameters(); + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(flyVector); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + Util.PlaySound(endSoundString, base.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage/JetpackOn.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage/JetpackOn.cs new file mode 100644 index 0000000..34dfbe1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage/JetpackOn.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace EntityStates.Mage; + +public class JetpackOn : BaseState +{ + public static float hoverVelocity; + + public static float hoverAcceleration; + + private Transform jetOnEffect; + + protected static Vector3 _tempVec3 = Vector3.one; + + public override void Reset() + { + base.Reset(); + jetOnEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + jetOnEffect = FindModelChild("JetOn"); + if ((bool)jetOnEffect) + { + jetOnEffect.gameObject.SetActive(value: true); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + float y = base.characterMotor.velocity.y; + y = Mathf.MoveTowards(y, hoverVelocity, hoverAcceleration * GetDeltaTime()); + base.characterMotor.velocity = new Vector3(base.characterMotor.velocity.x, y, base.characterMotor.velocity.z); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)jetOnEffect) + { + jetOnEffect.gameObject.SetActive(value: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Mage/MageCharacterMain.cs b/ilspy_dump/ror2_csproj/EntityStates.Mage/MageCharacterMain.cs new file mode 100644 index 0000000..4e3c38f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Mage/MageCharacterMain.cs @@ -0,0 +1,89 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Mage; + +public class MageCharacterMain : GenericCharacterMain +{ + private EntityStateMachine jetpackStateMachine; + + public bool jumpButtonState; + + private bool heldPress; + + private bool jumpToggledState; + + private float oldJumpHeldTime; + + private float jumpButtonHeldTime; + + public override void OnEnter() + { + base.OnEnter(); + jetpackStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Jet"); + } + + public override void ProcessJump() + { + if (hasCharacterMotor && hasInputBank && base.isAuthority) + { + if (NetworkUser.readOnlyLocalPlayersList[0]?.localUser?.userProfile.toggleArtificerHover ?? true) + { + if (base.inputBank.jump.down) + { + oldJumpHeldTime = jumpButtonHeldTime; + jumpButtonHeldTime += Time.deltaTime; + heldPress = oldJumpHeldTime < 0.5f && jumpButtonHeldTime >= 0.5f; + } + else + { + oldJumpHeldTime = 0f; + jumpButtonHeldTime = 0f; + heldPress = false; + } + if (!base.characterMotor.isGrounded) + { + if (base.characterMotor.jumpCount == base.characterBody.maxJumpCount) + { + if (base.inputBank.jump.justPressed) + { + jumpButtonState = !jumpButtonState; + } + } + else if (heldPress) + { + jumpButtonState = !jumpButtonState; + } + } + else + { + jumpButtonState = false; + } + } + else + { + jumpButtonState = base.inputBank.jump.down; + } + bool num = jumpButtonState && base.characterMotor.velocity.y < 0f && !base.characterMotor.isGrounded; + bool flag = jetpackStateMachine.state.GetType() == typeof(JetpackOn); + if (num && !flag) + { + jetpackStateMachine.SetNextState(new JetpackOn()); + } + if (!num && flag) + { + jetpackStateMachine.SetNextState(new Idle()); + } + } + base.ProcessJump(); + } + + public override void OnExit() + { + if (base.isAuthority && (bool)jetpackStateMachine) + { + jetpackStateMachine.SetNextState(new Idle()); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/BlinkState.cs b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/BlinkState.cs new file mode 100644 index 0000000..bf24ed6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/BlinkState.cs @@ -0,0 +1,7 @@ +using EntityStates.ImpBossMonster; + +namespace EntityStates.MagmaWorm; + +public class BlinkState : EntityStates.ImpBossMonster.BlinkState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/DeathState.cs new file mode 100644 index 0000000..fe08fbb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/DeathState.cs @@ -0,0 +1,80 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MagmaWorm; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialDeathExplosionEffect; + + public static string deathSoundString; + + public static float duration; + + private float stopwatch; + + public override void OnEnter() + { + base.OnEnter(); + WormBodyPositions2 component = GetComponent(); + WormBodyPositionsDriver component2 = GetComponent(); + if ((bool)component) + { + component2.yDamperConstant = 0f; + component2.ySpringConstant = 0f; + component2.maxTurnSpeed = 0f; + component.meatballCount = 0; + Util.PlaySound(deathSoundString, component.bones[0].gameObject); + } + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + PrintController printController = modelTransform.gameObject.AddComponent(); + printController.printTime = duration; + printController.enabled = true; + printController.startingPrintHeight = 99999f; + printController.maxPrintHeight = 99999f; + printController.startingPrintBias = 1f; + printController.maxPrintBias = 3.5f; + printController.animateFlowmapPower = true; + printController.startingFlowmapPower = 1.14f; + printController.maxFlowmapPower = 30f; + printController.disableWhenFinished = false; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + ParticleSystem[] componentsInChildren = modelTransform.GetComponentsInChildren(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].Stop(); + } + ChildLocator component3 = modelTransform.GetComponent(); + if ((bool)component3) + { + Transform transform = component3.FindChild("PP"); + if ((bool)transform) + { + PostProcessDuration component4 = transform.GetComponent(); + if ((bool)component4) + { + component4.enabled = true; + component4.maxDuration = duration; + } + } + } + if (NetworkServer.active) + { + EffectManager.SimpleMuzzleFlash(initialDeathExplosionEffect, base.gameObject, "HeadCenter", transmit: true); + } + } + + public override void FixedUpdate() + { + stopwatch += GetDeltaTime(); + if (NetworkServer.active && stopwatch > duration) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/Leap.cs b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/Leap.cs new file mode 100644 index 0000000..74af9ba --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/Leap.cs @@ -0,0 +1,100 @@ +using UnityEngine; + +namespace EntityStates.MagmaWorm; + +public class Leap : BaseState +{ + private enum LeapState + { + Burrow, + Ascend, + Fall, + Resurface + } + + private Transform modelBaseTransform; + + private readonly float diveDepth = 200f; + + private readonly Vector3 idealDiveVelocity = Vector3.down * 90f; + + private readonly Vector3 idealLeapVelocity = Vector3.up * 90f; + + private float leapAcceleration = 80f; + + private float resurfaceSpeed = 60f; + + private Vector3 velocity; + + private LeapState leapState; + + public override void OnEnter() + { + base.OnEnter(); + modelBaseTransform = GetModelBaseTransform(); + leapState = LeapState.Burrow; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + switch (leapState) + { + case LeapState.Burrow: + if ((bool)modelBaseTransform) + { + if (modelBaseTransform.position.y >= base.transform.position.y - diveDepth) + { + velocity = Vector3.MoveTowards(velocity, idealDiveVelocity, leapAcceleration * GetDeltaTime()); + modelBaseTransform.position += velocity * GetDeltaTime(); + } + else + { + leapState = LeapState.Ascend; + } + } + break; + case LeapState.Ascend: + if ((bool)modelBaseTransform) + { + if (modelBaseTransform.position.y <= base.transform.position.y) + { + velocity = Vector3.MoveTowards(velocity, idealLeapVelocity, leapAcceleration * GetDeltaTime()); + modelBaseTransform.position += velocity * GetDeltaTime(); + } + else + { + leapState = LeapState.Fall; + } + } + break; + case LeapState.Fall: + if ((bool)modelBaseTransform) + { + if (modelBaseTransform.position.y >= base.transform.position.y - diveDepth) + { + velocity += Physics.gravity * GetDeltaTime(); + modelBaseTransform.position += velocity * GetDeltaTime(); + } + else + { + leapState = LeapState.Resurface; + } + } + break; + case LeapState.Resurface: + velocity = Vector3.zero; + modelBaseTransform.position = Vector3.MoveTowards(modelBaseTransform.position, base.transform.position, resurfaceSpeed * GetDeltaTime()); + if (modelBaseTransform.position.y >= base.transform.position.y) + { + outer.SetNextStateToMain(); + } + break; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/SteerAtTarget.cs b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/SteerAtTarget.cs new file mode 100644 index 0000000..3b4adef --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/SteerAtTarget.cs @@ -0,0 +1,99 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MagmaWorm; + +public class SteerAtTarget : BaseSkillState +{ + private WormBodyPositionsDriver wormBodyPositionsDriver; + + private Vector3? targetPosition; + + private static readonly float fastTurnThreshold = Mathf.Cos(MathF.PI / 6f); + + private static readonly float slowTurnThreshold = Mathf.Cos(MathF.PI / 3f); + + private static readonly float fastTurnRate = 180f; + + private static readonly float slowTurnRate = 90f; + + public override void OnEnter() + { + base.OnEnter(); + wormBodyPositionsDriver = GetComponent(); + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + if (Util.CharacterRaycast(base.gameObject, aimRay, out var hitInfo, 1000f, LayerIndex.CommonMasks.bullet, QueryTriggerInteraction.UseGlobal)) + { + targetPosition = hitInfo.point; + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && targetPosition.HasValue) + { + Vector3 vector = targetPosition.Value - wormBodyPositionsDriver.chaserPosition; + if (vector != Vector3.zero && wormBodyPositionsDriver.chaserVelocity != Vector3.zero) + { + Vector3 normalized = vector.normalized; + Vector3 normalized2 = wormBodyPositionsDriver.chaserVelocity.normalized; + float num = Vector3.Dot(normalized, normalized2); + float num2 = 0f; + if (num >= slowTurnThreshold) + { + num2 = slowTurnRate; + if (num >= fastTurnThreshold) + { + num2 = fastTurnRate; + } + } + if (num2 != 0f) + { + wormBodyPositionsDriver.chaserVelocity = Vector3.RotateTowards(wormBodyPositionsDriver.chaserVelocity, vector, MathF.PI / 180f * num2 * GetDeltaTime(), 0f); + } + } + } + if (base.isAuthority && !IsKeyDownAuthority()) + { + outer.SetNextStateToMain(); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + if (targetPosition.HasValue) + { + writer.Write(value: true); + writer.Write(targetPosition.Value); + } + else + { + writer.Write(value: false); + } + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + if (reader.ReadBoolean()) + { + targetPosition = reader.ReadVector3(); + } + else + { + targetPosition = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/SwitchStance.cs b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/SwitchStance.cs new file mode 100644 index 0000000..9a4f9b2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MagmaWorm/SwitchStance.cs @@ -0,0 +1,70 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.MagmaWorm; + +public class SwitchStance : BaseState +{ + public static float leapingDuration = 10f; + + public static float groundStanceSpring = 3f; + + public static float groundStanceDamping = 3f; + + public static float groundStanceSpeedMultiplier = 1.5f; + + public static float leapStanceSpring = 3f; + + public static float leapStanceDamping = 1f; + + public static float leapStanceSpeedMultiplier = 1f; + + public override void OnEnter() + { + base.OnEnter(); + SetStanceParameters(leaping: true); + } + + public override void OnExit() + { + base.OnExit(); + SetStanceParameters(leaping: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= leapingDuration) + { + outer.SetNextStateToMain(); + } + } + + private void SetStanceParameters(bool leaping) + { + if (!NetworkServer.active) + { + return; + } + WormBodyPositions2 component = GetComponent(); + WormBodyPositionsDriver component2 = GetComponent(); + if ((bool)component) + { + if (leaping) + { + component2.ySpringConstant = leapStanceSpring; + component2.yDamperConstant = leapStanceDamping; + component.speedMultiplier = leapStanceSpeedMultiplier; + component2.allowShoving = false; + } + else + { + component2.ySpringConstant = groundStanceSpring; + component2.yDamperConstant = groundStanceDamping; + component.speedMultiplier = groundStanceSpeedMultiplier; + component2.allowShoving = true; + } + component.shouldFireMeatballsOnImpact = leaping; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/Lowered.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/Lowered.cs new file mode 100644 index 0000000..19a2c3e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/Lowered.cs @@ -0,0 +1,32 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MajorConstruct.Stance; + +public class Lowered : BaseState +{ + [SerializeField] + public GameObject attachmentPrefab; + + private NetworkedBodyAttachment attachment; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active && (bool)attachmentPrefab) + { + attachment = Object.Instantiate(attachmentPrefab).GetComponent(); + attachment.AttachToGameObjectAndSpawn(base.characterBody.gameObject); + } + } + + public override void OnExit() + { + if ((bool)attachment) + { + EntityState.Destroy(attachment.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/LoweredToRaised.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/LoweredToRaised.cs new file mode 100644 index 0000000..b154fb9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/LoweredToRaised.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MajorConstruct.Stance; + +public class LoweredToRaised : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParameter; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParameter, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new Raised()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/Raised.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/Raised.cs new file mode 100644 index 0000000..149f7cf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/Raised.cs @@ -0,0 +1,5 @@ +namespace EntityStates.MajorConstruct.Stance; + +public class Raised : BaseState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/RaisedToLowered.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/RaisedToLowered.cs new file mode 100644 index 0000000..7b85dac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Stance/RaisedToLowered.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MajorConstruct.Stance; + +public class RaisedToLowered : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParameter; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParameter, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new Lowered()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/ChargeLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/ChargeLaser.cs new file mode 100644 index 0000000..2186397 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/ChargeLaser.cs @@ -0,0 +1,53 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MajorConstruct.Weapon; + +public class ChargeLaser : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackParameterName, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new FireLaser()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/FireLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/FireLaser.cs new file mode 100644 index 0000000..72afc2b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/FireLaser.cs @@ -0,0 +1,107 @@ +using System; +using EntityStates.EngiTurret.EngiTurretWeapon; +using RoR2; +using RoR2.Audio; +using UnityEngine; + +namespace EntityStates.MajorConstruct.Weapon; + +public class FireLaser : FireBeam +{ + [SerializeField] + public float duration; + + [SerializeField] + public float aimMaxSpeed; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + [SerializeField] + public LoopSoundDef loopSoundDef; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + private AimAnimator.DirectionOverrideRequest animatorDirectionOverrideRequest; + + private Vector3 aimDirection; + + private Vector3 aimVelocity; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackParameterName, duration); + if ((bool)loopSoundDef) + { + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSoundDef); + } + AimAnimator component = GetComponent(); + if ((bool)component) + { + animatorDirectionOverrideRequest = component.RequestDirectionOverride(GetAimDirection); + } + aimDirection = GetTargetDirection(); + } + + public override void OnExit() + { + animatorDirectionOverrideRequest?.Dispose(); + LoopSoundManager.StopSoundLoopLocal(loopPtr); + base.OnExit(); + } + + public override void FixedUpdate() + { + aimDirection = Vector3.RotateTowards(aimDirection, GetTargetDirection(), aimMaxSpeed * (MathF.PI / 180f) * GetDeltaTime(), float.PositiveInfinity); + base.FixedUpdate(); + } + + public override void ModifyBullet(BulletAttack bulletAttack) + { + } + + protected override EntityState GetNextState() + { + return new TerminateLaser(GetBeamEndPoint()); + } + + public override bool ShouldFireLaser() + { + return duration > base.fixedAge; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } + + private Vector3 GetAimDirection() + { + return aimDirection; + } + + private Vector3 GetTargetDirection() + { + if ((bool)base.inputBank) + { + return base.inputBank.aimDirection; + } + return base.transform.forward; + } + + public override Ray GetLaserRay() + { + if ((bool)base.inputBank) + { + return new Ray(base.inputBank.aimOrigin, aimDirection); + } + return new Ray(base.transform.position, aimDirection); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/TerminateLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/TerminateLaser.cs new file mode 100644 index 0000000..4b7f64e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct.Weapon/TerminateLaser.cs @@ -0,0 +1,98 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MajorConstruct.Weapon; + +public class TerminateLaser : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public GameObject explosionEffectPrefab; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastForceMagnitude; + + [SerializeField] + public float blastRadius; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public string enterSoundString; + + private Vector3 blastPosition; + + public TerminateLaser() + { + } + + public TerminateLaser(Vector3 blastPosition) + { + this.blastPosition = blastPosition; + } + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackParameterName, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Util.PlaySound(enterSoundString, base.gameObject); + if (base.isAuthority) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * blastDamageCoefficient; + blastAttack.baseForce = blastForceMagnitude; + blastAttack.position = blastPosition; + blastAttack.radius = blastRadius; + blastAttack.bonusForce = blastBonusForce; + blastAttack.Fire(); + EffectData effectData = new EffectData + { + origin = blastPosition, + scale = blastRadius + }; + EffectManager.SpawnEffect(explosionEffectPrefab, effectData, transmit: true); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/Death.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/Death.cs new file mode 100644 index 0000000..adfe23d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/Death.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MajorConstruct; + +public class Death : GenericCharacterDeath +{ + [SerializeField] + public float duration; + + [SerializeField] + public GameObject beginEffect; + + [SerializeField] + public string beginMuzzleName; + + [SerializeField] + public GameObject padEffect; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayAnimation(animationLayerName, animationStateName); + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)beginEffect) + { + EffectManager.SimpleMuzzleFlash(beginEffect, base.gameObject, beginMuzzleName, transmit: false); + } + FindModelChild("Collision").gameObject.SetActive(value: false); + MasterSpawnSlotController component = GetComponent(); + if (NetworkServer.active) + { + _ = (bool)component; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/Spawn.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/Spawn.cs new file mode 100644 index 0000000..380d578 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/Spawn.cs @@ -0,0 +1,142 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MajorConstruct; + +public class Spawn : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public int numPads; + + [SerializeField] + public float padRingRadius; + + [SerializeField] + public float maxRaycastDistance; + + [SerializeField] + public GameObject padPrefab; + + [SerializeField] + public float maxPadDistance; + + [SerializeField] + public GameObject padEffectPrefab; + + [SerializeField] + public bool alignPadsToNormal; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public bool depleteStocksPrimary; + + [SerializeField] + public bool depleteStocksSecondary; + + [SerializeField] + public bool depleteStocksUtility; + + [SerializeField] + public bool depleteStocksSpecial; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Util.PlaySound(enterSoundString, base.gameObject); + MasterSpawnSlotController component = GetComponent(); + if (!NetworkServer.active || !padPrefab || !component) + { + return; + } + RaycastHit hitInfo = default(RaycastHit); + for (int i = 0; i < numPads; i++) + { + Quaternion quaternion = Quaternion.Euler(0f, 360f * ((float)i / (float)numPads), 0f); + Vector3 vector = base.characterBody.corePosition + quaternion * Vector3.forward * padRingRadius; + Vector3 origin = vector + Vector3.up * maxRaycastDistance; + if (Physics.Raycast(vector, Vector3.up, out hitInfo, maxRaycastDistance, LayerIndex.world.mask)) + { + origin = hitInfo.point; + } + if (Physics.Raycast(origin, Vector3.down, out hitInfo, maxRaycastDistance * 2f, LayerIndex.world.mask) && Vector3.Distance(base.characterBody.corePosition, hitInfo.point) < maxPadDistance) + { + if (alignPadsToNormal) + { + quaternion = Quaternion.FromToRotation(Vector3.up, hitInfo.normal) * quaternion; + } + GameObject obj = Object.Instantiate(padPrefab, hitInfo.point, quaternion); + NetworkedBodySpawnSlot component2 = obj.GetComponent(); + if ((bool)component2) + { + component.slots.Add(component2); + } + NetworkServer.Spawn(obj); + if ((bool)padEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = hitInfo.point, + rotation = quaternion + }; + EffectManager.SpawnEffect(padEffectPrefab, effectData, transmit: true); + } + } + } + } + + private void CheckForDepleteStocks(SkillSlot slot, bool deplete) + { + GenericSkill skill = base.skillLocator.GetSkill(slot); + if (deplete && (bool)skill) + { + skill.RemoveAllStocks(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (base.isAuthority) + { + CheckForDepleteStocks(SkillSlot.Primary, depleteStocksPrimary); + CheckForDepleteStocks(SkillSlot.Secondary, depleteStocksSecondary); + CheckForDepleteStocks(SkillSlot.Utility, depleteStocksUtility); + CheckForDepleteStocks(SkillSlot.Special, depleteStocksSpecial); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/SpawnMinorConstructs.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/SpawnMinorConstructs.cs new file mode 100644 index 0000000..847a367 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/SpawnMinorConstructs.cs @@ -0,0 +1,62 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MajorConstruct; + +public class SpawnMinorConstructs : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public int numToSpawn; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + MasterSpawnSlotController component = GetComponent(); + if (NetworkServer.active && (bool)component) + { + component.SpawnRandomOpen(numToSpawn, Run.instance.stageRng, base.gameObject); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/SwitchStance.cs b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/SwitchStance.cs new file mode 100644 index 0000000..9271aa1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MajorConstruct/SwitchStance.cs @@ -0,0 +1,32 @@ +using EntityStates.MajorConstruct.Stance; +using RoR2; + +namespace EntityStates.MajorConstruct; + +public class SwitchStance : BaseState +{ + private const string stanceStateMachineName = "Stance"; + + public override void OnEnter() + { + base.OnEnter(); + if (!base.isAuthority) + { + return; + } + EntityStateMachine entityStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Stance"); + EntityState state = entityStateMachine.state; + if (!(state is Raised)) + { + if (state is Lowered) + { + entityStateMachine.SetNextState(new LoweredToRaised()); + } + } + else + { + entityStateMachine.SetNextState(new RaisedToLowered()); + } + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/ExitShield.cs b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/ExitShield.cs new file mode 100644 index 0000000..ba763d4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/ExitShield.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +namespace EntityStates.MegaConstruct; + +public class ExitShield : BaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + [SerializeField] + public float baseDuration; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackParameterName, baseDuration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > baseDuration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/FallingDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/FallingDeath.cs new file mode 100644 index 0000000..a2c8b58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/FallingDeath.cs @@ -0,0 +1,77 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MegaConstruct; + +public class FallingDeath : GenericCharacterDeath +{ + public static float deathDelay; + + public static GameObject enterEffectPrefab; + + public static GameObject deathEffectPrefab; + + public static float explosionForce; + + public static string standableSurfaceChildName; + + private bool hasDied; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleImpactEffect(enterEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: true); + MasterSpawnSlotController component = GetComponent(); + if (NetworkServer.active && (bool)component) + { + component.KillAll(); + } + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + Transform transform = modelChildLocator.FindChild(standableSurfaceChildName); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > deathDelay && NetworkServer.active && !hasDied) + { + hasDied = true; + EffectManager.SimpleImpactEffect(deathEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: true); + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + Rigidbody component = GetComponent(); + RagdollController component2 = modelTransform.GetComponent(); + if ((bool)component2 && (bool)component) + { + component2.BeginRagdoll(component.velocity); + } + ExplodeRigidbodiesOnStart component3 = modelTransform.GetComponent(); + if ((bool)component3) + { + component3.force = explosionForce; + component3.enabled = true; + } + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.enabled = false; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/RaiseShield.cs b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/RaiseShield.cs new file mode 100644 index 0000000..6e7253d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/RaiseShield.cs @@ -0,0 +1,61 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MegaConstruct; + +public class RaiseShield : FlyState +{ + [SerializeField] + public GameObject attachmentPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationEnterStateName; + + [SerializeField] + public float duration; + + private NetworkedBodyAttachment attachment; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active && (bool)attachmentPrefab) + { + attachment = Object.Instantiate(attachmentPrefab).GetComponent(); + attachment.AttachToGameObjectAndSpawn(base.characterBody.gameObject); + } + MasterSpawnSlotController component = GetComponent(); + if (NetworkServer.active && (bool)component) + { + component.SpawnAllOpen(base.gameObject, Run.instance.stageRng); + } + PlayAnimation(animationLayerName, animationEnterStateName); + } + + protected override bool CanExecuteSkill(GenericSkill skillSlot) + { + return false; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new ExitShield()); + } + } + + public override void OnExit() + { + if (NetworkServer.active && (bool)attachment) + { + EntityState.Destroy(attachment.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/Spawn.cs b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/Spawn.cs new file mode 100644 index 0000000..15d188c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/Spawn.cs @@ -0,0 +1,90 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MegaConstruct; + +public class Spawn : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public int numPads; + + [SerializeField] + public string padChildLocatorName; + + [SerializeField] + public GameObject padPrefab; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public bool depleteStocksPrimary; + + [SerializeField] + public bool depleteStocksSecondary; + + [SerializeField] + public bool depleteStocksUtility; + + [SerializeField] + public bool depleteStocksSpecial; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + private void CheckForDepleteStocks(SkillSlot slot, bool deplete) + { + GenericSkill skill = base.skillLocator.GetSkill(slot); + if (deplete && (bool)skill) + { + skill.RemoveAllStocks(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (base.isAuthority) + { + CheckForDepleteStocks(SkillSlot.Primary, depleteStocksPrimary); + CheckForDepleteStocks(SkillSlot.Secondary, depleteStocksSecondary); + CheckForDepleteStocks(SkillSlot.Utility, depleteStocksUtility); + CheckForDepleteStocks(SkillSlot.Special, depleteStocksSpecial); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/SpawnMinorConstructs.cs b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/SpawnMinorConstructs.cs new file mode 100644 index 0000000..52f7f08 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MegaConstruct/SpawnMinorConstructs.cs @@ -0,0 +1,62 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MegaConstruct; + +public class SpawnMinorConstructs : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public int numToSpawn; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + MasterSpawnSlotController component = GetComponent(); + if (NetworkServer.active && (bool)component) + { + component.SpawnRandomOpen(numToSpawn, Run.instance.stageRng, base.gameObject); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc.Weapon/GroundLight2.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc.Weapon/GroundLight2.cs new file mode 100644 index 0000000..d44e76c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc.Weapon/GroundLight2.cs @@ -0,0 +1,154 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc.Weapon; + +public class GroundLight2 : BasicMeleeAttack, SteppedSkillDef.IStepSetter +{ + public int step; + + public static float recoilAmplitude; + + public static float baseDurationBeforeInterruptable; + + [SerializeField] + public float bloom; + + public static float comboFinisherBaseDuration; + + public static GameObject comboFinisherSwingEffectPrefab; + + public static float comboFinisherhitPauseDuration; + + public static float comboFinisherDamageCoefficient; + + public static float comboFinisherBloom; + + public static float comboFinisherBaseDurationBeforeInterruptable; + + public static string slash1Sound; + + public static string slash3Sound; + + private string animationStateName; + + private float durationBeforeInterruptable; + + private bool isComboFinisher => step == 2; + + protected override bool allowExitFire + { + get + { + if ((bool)base.characterBody) + { + return !base.characterBody.isSprinting; + } + return false; + } + } + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + step = i; + } + + public override void OnEnter() + { + if (isComboFinisher) + { + swingEffectPrefab = comboFinisherSwingEffectPrefab; + hitPauseDuration = comboFinisherhitPauseDuration; + damageCoefficient = comboFinisherDamageCoefficient; + bloom = comboFinisherBloom; + hitBoxGroupName = "SwordLarge"; + baseDuration = comboFinisherBaseDuration; + } + base.OnEnter(); + base.characterDirection.forward = GetAimRay().direction; + durationBeforeInterruptable = (isComboFinisher ? (comboFinisherBaseDurationBeforeInterruptable / attackSpeedStat) : (baseDurationBeforeInterruptable / attackSpeedStat)); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + if (isComboFinisher) + { + overlapAttack.damageType = DamageType.ApplyMercExpose; + } + } + + protected override void PlayAnimation() + { + animationStateName = ""; + string soundString = null; + switch (step) + { + case 0: + animationStateName = "GroundLight1"; + soundString = slash1Sound; + break; + case 1: + animationStateName = "GroundLight2"; + soundString = slash1Sound; + break; + case 2: + animationStateName = "GroundLight3"; + soundString = slash3Sound; + break; + } + bool @bool = animator.GetBool("isMoving"); + bool bool2 = animator.GetBool("isGrounded"); + if (!@bool && bool2) + { + PlayCrossfade("FullBody, Override", animationStateName, "GroundLight.playbackRate", duration, 0.05f); + } + else + { + PlayCrossfade("Gesture, Additive", animationStateName, "GroundLight.playbackRate", duration, 0.05f); + PlayCrossfade("Gesture, Override", animationStateName, "GroundLight.playbackRate", duration, 0.05f); + } + Util.PlaySound(soundString, base.gameObject); + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + base.characterBody.AddSpreadBloom(bloom); + } + + protected override void BeginMeleeAttackEffect() + { + swingEffectMuzzleString = animationStateName; + AddRecoil(-0.1f * recoilAmplitude, 0.1f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + base.BeginMeleeAttackEffect(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)step); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + step = reader.ReadByte(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge < durationBeforeInterruptable)) + { + return InterruptPriority.Skill; + } + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc.Weapon/ThrowEvisProjectile.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc.Weapon/ThrowEvisProjectile.cs new file mode 100644 index 0000000..5b9eae5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc.Weapon/ThrowEvisProjectile.cs @@ -0,0 +1,47 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Merc.Weapon; + +public class ThrowEvisProjectile : GenericProjectileBaseState +{ + public static float shortHopVelocity; + + private static int GroundLight3StateHash = Animator.StringToHash("GroundLight3"); + + private static int GroundLightParamHash = Animator.StringToHash("GroundLight.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity.y = Mathf.Max(base.characterMotor.velocity.y, shortHopVelocity); + } + } + + protected override void PlayAnimation(float duration) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + bool @bool = modelAnimator.GetBool("isMoving"); + bool bool2 = modelAnimator.GetBool("isGrounded"); + if (@bool || !bool2) + { + PlayAnimation("Gesture, Additive", GroundLight3StateHash, GroundLightParamHash, duration); + PlayAnimation("Gesture, Override", GroundLight3StateHash, GroundLightParamHash, duration); + } + else + { + PlayAnimation("FullBody, Override", GroundLight3StateHash, GroundLightParamHash, duration); + } + } + } + + protected override Ray ModifyProjectileAimRay(Ray aimRay) + { + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref aimRay, projectilePrefab, base.gameObject); + return aimRay; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/Assaulter.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/Assaulter.cs new file mode 100644 index 0000000..8bffd86 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/Assaulter.cs @@ -0,0 +1,245 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class Assaulter : BaseState +{ + private Transform modelTransform; + + public static GameObject dashPrefab; + + public static float smallHopVelocity; + + public static float dashPrepDuration; + + public static float dashDuration = 0.3f; + + public static float speedCoefficient = 25f; + + public static string beginSoundString; + + public static string endSoundString; + + public static float damageCoefficient; + + public static float procCoefficient; + + public static GameObject hitEffectPrefab; + + public static float hitPauseDuration; + + private float stopwatch; + + private Vector3 dashVector = Vector3.zero; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private OverlapAttack overlapAttack; + + private ChildLocator childLocator; + + private bool isDashing; + + private bool inHitPause; + + private float hitPauseTimer; + + private CameraTargetParams.AimRequest aimRequest; + + private int originalLayer; + + private static int AssaulterPrepStateHash = Animator.StringToHash("AssaulterPrep"); + + private static int AssaulterPrepParamHash = Animator.StringToHash("AssaulterPrep.playbackRate"); + + private static int EvisLoopExitStateHash = Animator.StringToHash("EvisLoopExit"); + + public bool hasHit { get; private set; } + + public int dashIndex { private get; set; } + + public override void Reset() + { + base.Reset(); + modelTransform = null; + stopwatch = 0f; + dashVector = Vector3.zero; + animator = null; + characterModel = null; + hurtboxGroup = null; + if (overlapAttack != null) + { + overlapAttack.Reset(); + } + childLocator = null; + isDashing = false; + inHitPause = false; + hitPauseTimer = 0f; + hasHit = false; + dashIndex = 0; + } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + childLocator = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + if ((bool)childLocator) + { + childLocator.FindChild("PreDashEffect").gameObject.SetActive(value: true); + } + } + SmallHop(base.characterMotor, smallHopVelocity); + PlayAnimation("FullBody, Override", AssaulterPrepStateHash, AssaulterPrepParamHash, dashPrepDuration); + dashVector = base.inputBank.aimDirection; + overlapAttack = InitMeleeOverlap(damageCoefficient, hitEffectPrefab, modelTransform, "Assaulter"); + overlapAttack.damageType = DamageType.Stun1s; + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + } + + private void CreateDashEffect() + { + Transform transform = childLocator.FindChild("DashCenter"); + if ((bool)transform && (bool)dashPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(dashPrefab)) + { + Object.Instantiate(dashPrefab, transform.position, Util.QuaternionSafeLookRotation(dashVector), transform); + } + else + { + EffectManager.GetAndActivatePooledEffect(dashPrefab, transform.position, Util.QuaternionSafeLookRotation(dashVector), transform); + } + } + if ((bool)childLocator) + { + childLocator.FindChild("PreDashEffect").gameObject.SetActive(value: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterDirection.forward = dashVector; + if (stopwatch > dashPrepDuration / attackSpeedStat && !isDashing) + { + isDashing = true; + dashVector = base.inputBank.aimDirection; + CreateDashEffect(); + PlayCrossfade("FullBody, Override", "AssaulterLoop", 0.1f); + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 0.7f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matMercEnergized"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + } + } + float deltaTime = GetDeltaTime(); + if (!isDashing) + { + stopwatch += deltaTime; + } + else if (base.isAuthority) + { + base.characterMotor.velocity = Vector3.zero; + if (!inHitPause) + { + bool num = overlapAttack.Fire(); + stopwatch += deltaTime; + if (num) + { + if (!hasHit) + { + hasHit = true; + } + inHitPause = true; + hitPauseTimer = hitPauseDuration / attackSpeedStat; + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance2 = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance2.duration = hitPauseDuration / attackSpeedStat; + temporaryOverlayInstance2.animateShaderAlpha = true; + temporaryOverlayInstance2.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance2.destroyComponentOnEnd = true; + temporaryOverlayInstance2.originalMaterial = LegacyResourcesAPI.Load("Materials/matMercEvisTarget"); + temporaryOverlayInstance2.AddToCharacterModel(modelTransform.GetComponent()); + } + } + base.characterMotor.rootMotion += dashVector * moveSpeedStat * speedCoefficient * deltaTime; + } + else + { + hitPauseTimer -= deltaTime; + if (hitPauseTimer < 0f) + { + inHitPause = false; + } + } + } + if (stopwatch >= dashDuration + dashPrepDuration / attackSpeedStat && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + Util.PlaySound(endSoundString, base.gameObject); + if (base.isAuthority) + { + base.characterMotor.velocity *= 0.1f; + SmallHop(base.characterMotor, smallHopVelocity); + } + aimRequest?.Dispose(); + if ((bool)childLocator) + { + childLocator.FindChild("PreDashEffect").gameObject.SetActive(value: false); + } + PlayAnimation("FullBody, Override", EvisLoopExitStateHash); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility.buffIndex); + } + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)dashIndex); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dashIndex = reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/Assaulter2.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/Assaulter2.cs new file mode 100644 index 0000000..d5a9b31 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/Assaulter2.cs @@ -0,0 +1,133 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class Assaulter2 : BasicMeleeAttack +{ + public static float speedCoefficientOnExit; + + public static float speedCoefficient; + + public static string endSoundString; + + public static float exitSmallHop; + + public static GameObject selfOnHitOverlayEffectPrefab; + + public bool grantAnotherDash; + + private Transform modelTransform; + + private Vector3 dashVector; + + private int originalLayer; + + private static int EvisLoopExitStateHash = Animator.StringToHash("EvisLoopExit"); + + private static int AssaulterLoopStateHash = Animator.StringToHash("AssaulterLoop"); + + private bool bufferedSkill2; + + private Vector3 dashVelocity => dashVector * moveSpeedStat * speedCoefficient; + + public override void OnEnter() + { + base.OnEnter(); + dashVector = base.inputBank.aimDirection; + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.velocity = Vector3.zero; + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 0.7f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matMercEnergized"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + } + PlayCrossfade("FullBody, Override", "AssaulterLoop", 0.1f); + base.characterDirection.forward = base.characterMotor.velocity.normalized; + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + } + base.characterMotor.velocity *= speedCoefficientOnExit; + SmallHop(base.characterMotor, exitSmallHop); + Util.PlaySound(endSoundString, base.gameObject); + PlayAnimation("FullBody, Override", EvisLoopExitStateHash); + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + base.OnExit(); + } + + protected override void PlayAnimation() + { + base.PlayAnimation(); + PlayCrossfade("FullBody, Override", AssaulterLoopStateHash, 0.1f); + } + + protected override void AuthorityFixedUpdate() + { + base.AuthorityFixedUpdate(); + if (!base.authorityInHitPause) + { + base.characterMotor.rootMotion += dashVelocity * GetDeltaTime(); + base.characterDirection.forward = dashVelocity; + base.characterDirection.moveVector = dashVelocity; + base.characterBody.isSprinting = true; + if (bufferedSkill2) + { + base.skillLocator.secondary.ExecuteIfReady(); + bufferedSkill2 = false; + } + } + if ((bool)base.skillLocator && base.skillLocator.secondary.IsReady() && base.inputBank.skill2.down) + { + bufferedSkill2 = true; + } + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + overlapAttack.damageType = DamageType.Stun1s; + overlapAttack.damage = damageCoefficient * damageStat; + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + grantAnotherDash = true; + float num = hitPauseDuration / attackSpeedStat; + if ((bool)selfOnHitOverlayEffectPrefab && num > 1f / 30f) + { + EffectData effectData = new EffectData + { + origin = base.transform.position, + genericFloat = hitPauseDuration / attackSpeedStat + }; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(selfOnHitOverlayEffectPrefab, effectData, transmit: true); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/Evis.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/Evis.cs new file mode 100644 index 0000000..0c384de --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/Evis.cs @@ -0,0 +1,199 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class Evis : BaseState +{ + private Transform modelTransform; + + public static GameObject blinkPrefab; + + public static float duration = 2f; + + public static float damageCoefficient; + + public static float damageFrequency; + + public static float procCoefficient; + + public static string beginSoundString; + + public static string endSoundString; + + public static float maxRadius; + + public static GameObject hitEffectPrefab; + + public static string slashSoundString; + + public static string impactSoundString; + + public static string dashSoundString; + + public static float slashPitch; + + public static float smallHopVelocity; + + public static float lingeringInvincibilityDuration; + + private Animator animator; + + private CharacterModel characterModel; + + private float stopwatch; + + private float attackStopwatch; + + private bool crit; + + private static float minimumDuration = 0.5f; + + private CameraTargetParams.AimRequest aimRequest; + + public override void OnEnter() + { + base.OnEnter(); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + Util.PlayAttackSpeedSound(beginSoundString, base.gameObject, 1.2f); + crit = Util.CheckRoll(critStat, base.characterBody.master); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + attackStopwatch += deltaTime; + float num = 1f / damageFrequency / attackSpeedStat; + if (attackStopwatch >= num) + { + attackStopwatch -= num; + HurtBox hurtBox = SearchForTarget(); + if ((bool)hurtBox) + { + Util.PlayAttackSpeedSound(slashSoundString, base.gameObject, slashPitch); + Util.PlaySound(dashSoundString, base.gameObject); + Util.PlaySound(impactSoundString, base.gameObject); + HurtBoxGroup hurtBoxGroup = hurtBox.hurtBoxGroup; + HurtBox hurtBox2 = hurtBoxGroup.hurtBoxes[Random.Range(0, hurtBoxGroup.hurtBoxes.Length - 1)]; + if ((bool)hurtBox2) + { + Vector3 position = hurtBox2.transform.position; + Vector2 normalized = Random.insideUnitCircle.normalized; + EffectManager.SimpleImpactEffect(normal: new Vector3(normalized.x, 0f, normalized.y), effectPrefab: hitEffectPrefab, hitPos: position, transmit: false); + Transform transform = hurtBox.hurtBoxGroup.transform; + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(transform.gameObject); + temporaryOverlayInstance.duration = num; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matMercEvisTarget"); + temporaryOverlayInstance.AddToCharacterModel(transform.GetComponent()); + if (NetworkServer.active) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageCoefficient * damageStat; + damageInfo.attacker = base.gameObject; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = hurtBox2.transform.position; + damageInfo.crit = crit; + hurtBox2.healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, hurtBox2.healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, hurtBox2.healthComponent.gameObject); + } + } + } + else if (base.isAuthority && stopwatch > minimumDuration) + { + outer.SetNextStateToMain(); + } + } + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = Vector3.zero; + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private HurtBox SearchForTarget() + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = base.transform.position; + bullseyeSearch.searchDirection = Random.onUnitSphere; + bullseyeSearch.maxDistanceFilter = maxRadius; + bullseyeSearch.teamMaskFilter = TeamMask.GetUnprotectedTeams(GetTeam()); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + return bullseyeSearch.GetResults().FirstOrDefault(); + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(Vector3.up); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: false); + } + + public override void OnExit() + { + Util.PlaySound(endSoundString, base.gameObject); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 0.6f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matMercEvisTarget"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + TemporaryOverlayInstance temporaryOverlayInstance2 = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance2.duration = 0.7f; + temporaryOverlayInstance2.animateShaderAlpha = true; + temporaryOverlayInstance2.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance2.destroyComponentOnEnd = true; + temporaryOverlayInstance2.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashExpanded"); + temporaryOverlayInstance2.AddToCharacterModel(modelTransform.GetComponent()); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + aimRequest?.Dispose(); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, lingeringInvincibilityDuration); + } + Util.PlaySound(endSoundString, base.gameObject); + SmallHop(base.characterMotor, smallHopVelocity); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/EvisDash.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/EvisDash.cs new file mode 100644 index 0000000..7540d16 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/EvisDash.cs @@ -0,0 +1,155 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class EvisDash : BaseState +{ + private Transform modelTransform; + + public static GameObject blinkPrefab; + + private float stopwatch; + + private Vector3 dashVector = Vector3.zero; + + public static float smallHopVelocity; + + public static float dashPrepDuration; + + public static float dashDuration = 0.3f; + + public static float speedCoefficient = 25f; + + public static string beginSoundString; + + public static string endSoundString; + + public static float overlapSphereRadius; + + public static float lollypopFactor; + + private Animator animator; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private bool isDashing; + + private CameraTargetParams.AimRequest aimRequest; + + private static int EvisPrepStateHash = Animator.StringToHash("EvisPrep"); + + private static int EvisPrepParamHash = Animator.StringToHash("EvisPrep.playbackRate"); + + private static int EvisLoopExitStateHash = Animator.StringToHash("EvisLoopExit"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if ((bool)modelTransform) + { + animator = modelTransform.GetComponent(); + characterModel = modelTransform.GetComponent(); + } + if (base.isAuthority) + { + SmallHop(base.characterMotor, smallHopVelocity); + } + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + PlayAnimation("FullBody, Override", EvisPrepStateHash, EvisPrepParamHash, dashPrepDuration); + dashVector = base.inputBank.aimDirection; + base.characterDirection.forward = dashVector; + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(dashVector); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch > dashPrepDuration && !isDashing) + { + isDashing = true; + dashVector = base.inputBank.aimDirection; + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + PlayCrossfade("FullBody, Override", "EvisLoop", 0.1f); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 0.6f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashBright"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + TemporaryOverlayInstance temporaryOverlayInstance2 = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance2.duration = 0.7f; + temporaryOverlayInstance2.animateShaderAlpha = true; + temporaryOverlayInstance2.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance2.destroyComponentOnEnd = true; + temporaryOverlayInstance2.originalMaterial = LegacyResourcesAPI.Load("Materials/matHuntressFlashExpanded"); + temporaryOverlayInstance2.AddToCharacterModel(modelTransform.GetComponent()); + } + } + bool flag = stopwatch >= dashDuration + dashPrepDuration; + if (isDashing) + { + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.rootMotion += dashVector * (moveSpeedStat * speedCoefficient * GetDeltaTime()); + } + if (base.isAuthority) + { + Collider[] colliders; + int num = HGPhysics.OverlapSphere(out colliders, base.transform.position, base.characterBody.radius + overlapSphereRadius * (flag ? lollypopFactor : 1f), LayerIndex.entityPrecise.mask); + for (int i = 0; i < num; i++) + { + HurtBox component = colliders[i].GetComponent(); + if ((bool)component && component.healthComponent != base.healthComponent) + { + Evis nextState = new Evis(); + outer.SetNextState(nextState); + break; + } + } + HGPhysics.ReturnResults(colliders); + } + } + if (flag && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + Util.PlaySound(endSoundString, base.gameObject); + base.characterMotor.velocity *= 0.1f; + SmallHop(base.characterMotor, smallHopVelocity); + aimRequest?.Dispose(); + PlayAnimation("FullBody, Override", EvisLoopExitStateHash); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/FocusedAssaultDash.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/FocusedAssaultDash.cs new file mode 100644 index 0000000..3d5baa4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/FocusedAssaultDash.cs @@ -0,0 +1,221 @@ +using RoR2; +using RoR2.Networking; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class FocusedAssaultDash : BasicMeleeAttack +{ + [SerializeField] + public float speedCoefficientOnExit; + + [SerializeField] + public float speedCoefficient; + + [SerializeField] + public string endSoundString; + + [SerializeField] + public float exitSmallHop; + + [SerializeField] + public float delayedDamageCoefficient; + + [SerializeField] + public float delayedProcCoefficient; + + [SerializeField] + public float delay; + + [SerializeField] + public string enterAnimationLayerName = "FullBody, Override"; + + [SerializeField] + public string enterAnimationStateName = "AssaulterLoop"; + + [SerializeField] + public float enterAnimationCrossfadeDuration = 0.1f; + + [SerializeField] + public string exitAnimationLayerName = "FullBody, Override"; + + [SerializeField] + public string exitAnimationStateName = "EvisLoopExit"; + + [SerializeField] + public Material enterOverlayMaterial; + + [SerializeField] + public float enterOverlayDuration = 0.7f; + + [SerializeField] + public GameObject delayedEffectPrefab; + + [SerializeField] + public GameObject orbEffect; + + [SerializeField] + public float delayPerHit; + + [SerializeField] + public GameObject selfOnHitOverlayEffectPrefab; + + private Transform modelTransform; + + private Vector3 dashVector; + + private int originalLayer; + + private int currentHitCount; + + private Vector3 dashVelocity => dashVector * moveSpeedStat * speedCoefficient; + + public override void OnEnter() + { + base.OnEnter(); + dashVector = base.inputBank.aimDirection; + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(base.teamComponent.teamIndex).intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + base.characterMotor.Motor.ForceUnground(); + base.characterMotor.velocity = Vector3.zero; + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = enterOverlayDuration; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = enterOverlayMaterial; + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + } + PlayCrossfade(enterAnimationLayerName, enterAnimationStateName, enterAnimationCrossfadeDuration); + base.characterDirection.forward = base.characterMotor.velocity.normalized; + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + } + base.characterMotor.velocity *= speedCoefficientOnExit; + SmallHop(base.characterMotor, exitSmallHop); + Util.PlaySound(endSoundString, base.gameObject); + PlayAnimation(exitAnimationLayerName, exitAnimationStateName); + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + base.OnExit(); + } + + protected override void PlayAnimation() + { + base.PlayAnimation(); + PlayCrossfade(enterAnimationLayerName, enterAnimationStateName, enterAnimationCrossfadeDuration); + } + + protected override void AuthorityFixedUpdate() + { + base.AuthorityFixedUpdate(); + if (!base.authorityInHitPause) + { + base.characterMotor.rootMotion += dashVelocity * GetDeltaTime(); + base.characterDirection.forward = dashVelocity; + base.characterDirection.moveVector = dashVelocity; + base.characterBody.isSprinting = true; + } + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + overlapAttack.damage = damageCoefficient * damageStat; + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + float num = hitPauseDuration / attackSpeedStat; + if ((bool)selfOnHitOverlayEffectPrefab && num > 1f / 30f) + { + EffectData effectData = new EffectData + { + origin = base.transform.position, + genericFloat = hitPauseDuration / attackSpeedStat + }; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(selfOnHitOverlayEffectPrefab, effectData, transmit: true); + } + foreach (HurtBox hitResult in hitResults) + { + currentHitCount++; + float damageValue = base.characterBody.damage * delayedDamageCoefficient; + float num2 = delay + delayPerHit * (float)currentHitCount; + bool isCrit = RollCrit(); + HandleHit(base.gameObject, hitResult, damageValue, delayedProcCoefficient, isCrit, num2, orbEffect, delayedEffectPrefab); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private static void HandleHit(GameObject attackerObject, HurtBox victimHurtBox, float damageValue, float procCoefficient, bool isCrit, float delay, GameObject orbEffectPrefab, GameObject orbImpactEffectPrefab) + { + if (!NetworkServer.active) + { + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(77); + networkWriter.Write(attackerObject); + networkWriter.Write(HurtBoxReference.FromHurtBox(victimHurtBox)); + networkWriter.Write(damageValue); + networkWriter.Write(procCoefficient); + networkWriter.Write(isCrit); + networkWriter.Write(delay); + networkWriter.WriteEffectIndex(EffectCatalog.FindEffectIndexFromPrefab(orbEffectPrefab)); + networkWriter.WriteEffectIndex(EffectCatalog.FindEffectIndexFromPrefab(orbImpactEffectPrefab)); + networkWriter.FinishMessage(); + ClientScene.readyConnection?.SendWriter(networkWriter, QosChannelIndex.defaultReliable.intVal); + } + else if ((bool)victimHurtBox && (bool)victimHurtBox.healthComponent) + { + SetStateOnHurt.SetStunOnObject(victimHurtBox.healthComponent.gameObject, delay); + OrbManager.instance.AddOrb(new DelayedHitOrb + { + attacker = attackerObject, + target = victimHurtBox, + damageColorIndex = DamageColorIndex.Default, + damageValue = damageValue, + damageType = DamageType.ApplyMercExpose, + isCrit = isCrit, + procChainMask = default(ProcChainMask), + procCoefficient = procCoefficient, + delay = delay, + orbEffect = orbEffectPrefab, + delayedEffectPrefab = orbImpactEffectPrefab + }); + } + } + + [NetworkMessageHandler(msgType = 77, client = false, server = true)] + private static void HandleReportMercFocusedAssaultHitReplaceMeLater(NetworkMessage netMsg) + { + GameObject attackerObject = netMsg.reader.ReadGameObject(); + HurtBox victimHurtBox = netMsg.reader.ReadHurtBoxReference().ResolveHurtBox(); + float damageValue = netMsg.reader.ReadSingle(); + float num = netMsg.reader.ReadSingle(); + bool isCrit = netMsg.reader.ReadBoolean(); + float num2 = netMsg.reader.ReadSingle(); + GameObject orbEffectPrefab = EffectCatalog.GetEffectDef(netMsg.reader.ReadEffectIndex())?.prefab ?? null; + GameObject orbImpactEffectPrefab = EffectCatalog.GetEffectDef(netMsg.reader.ReadEffectIndex())?.prefab ?? null; + HandleHit(attackerObject, victimHurtBox, damageValue, num, isCrit, num2, orbEffectPrefab, orbImpactEffectPrefab); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/FocusedAssaultPrep.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/FocusedAssaultPrep.cs new file mode 100644 index 0000000..ef9b266 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/FocusedAssaultPrep.cs @@ -0,0 +1,74 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class FocusedAssaultPrep : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float smallHopVelocity; + + [SerializeField] + public string enterSoundString; + + private float duration; + + private static int AssaulterPrepStateHash = Animator.StringToHash("AssaulterPrep"); + + private static int AssaulterPrepParamHash = Animator.StringToHash("AssaulterPrep.playbackRate"); + + public int dashIndex { private get; set; } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("FullBody, Override", AssaulterPrepStateHash, AssaulterPrepParamHash, baseDuration); + FindModelChildGameObject("PreDashEffect")?.SetActive(value: true); + Util.PlaySound(enterSoundString, base.gameObject); + Ray aimRay = GetAimRay(); + base.characterDirection.forward = aimRay.direction; + base.characterDirection.moveVector = aimRay.direction; + SmallHop(base.characterMotor, smallHopVelocity); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, 0.2f); + } + FindModelChildGameObject("PreDashEffect")?.SetActive(value: false); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new FocusedAssaultDash()); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)dashIndex); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dashIndex = reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/GroundLight.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/GroundLight.cs new file mode 100644 index 0000000..489f446 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/GroundLight.cs @@ -0,0 +1,250 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class GroundLight : BaseState +{ + public enum ComboState + { + GroundLight1, + GroundLight2, + GroundLight3 + } + + private struct ComboStateInfo + { + private string mecanimStateName; + + private string mecanimPlaybackRateName; + } + + public static float baseComboAttackDuration; + + public static float baseFinisherAttackDuration; + + public static float baseEarlyExitDuration; + + public static string comboAttackSoundString; + + public static string finisherAttackSoundString; + + public static float comboDamageCoefficient; + + public static float finisherDamageCoefficient; + + public static float forceMagnitude; + + public static GameObject comboHitEffectPrefab; + + public static GameObject finisherHitEffectPrefab; + + public static GameObject comboSwingEffectPrefab; + + public static GameObject finisherSwingEffectPrefab; + + public static float hitPauseDuration; + + public static float selfForceMagnitude; + + public static string hitSoundString; + + public static float slashPitch; + + private float stopwatch; + + private float attackDuration; + + private float earlyExitDuration; + + private Animator animator; + + private OverlapAttack overlapAttack; + + private float hitPauseTimer; + + private bool isInHitPause; + + private bool hasSwung; + + private bool hasHit; + + private GameObject swingEffectInstance; + + public ComboState comboState; + + private Vector3 characterForward; + + private string slashChildName; + + private HitStopCachedState hitStopCachedState; + + private GameObject swingEffectPrefab; + + private GameObject hitEffectPrefab; + + private string attackSoundString; + + private static int GroundLight1StateHash = Animator.StringToHash("GroundLight1"); + + private static int GroundLight2StateHash = Animator.StringToHash("GroundLight2"); + + private static int GroundLight3StateHash = Animator.StringToHash("GroundLight3"); + + private static int GroundLightParamHash = Animator.StringToHash("GroundLight.playbackRate"); + + private static int SwordactiveParamHash = Animator.StringToHash("Sword.active"); + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + earlyExitDuration = baseEarlyExitDuration / attackSpeedStat; + animator = GetModelAnimator(); + bool @bool = animator.GetBool("isMoving"); + bool bool2 = animator.GetBool("isGrounded"); + switch (comboState) + { + case ComboState.GroundLight1: + attackDuration = baseComboAttackDuration / attackSpeedStat; + overlapAttack = InitMeleeOverlap(comboDamageCoefficient, hitEffectPrefab, GetModelTransform(), "Sword"); + if (@bool || !bool2) + { + PlayAnimation("Gesture, Additive", GroundLight1StateHash, GroundLightParamHash, attackDuration); + PlayAnimation("Gesture, Override", GroundLight1StateHash, GroundLightParamHash, attackDuration); + } + else + { + PlayAnimation("FullBody, Override", GroundLight1StateHash, GroundLightParamHash, attackDuration); + } + slashChildName = "GroundLight1Slash"; + swingEffectPrefab = comboSwingEffectPrefab; + hitEffectPrefab = comboHitEffectPrefab; + attackSoundString = comboAttackSoundString; + break; + case ComboState.GroundLight2: + attackDuration = baseComboAttackDuration / attackSpeedStat; + overlapAttack = InitMeleeOverlap(comboDamageCoefficient, hitEffectPrefab, GetModelTransform(), "Sword"); + if (@bool || !bool2) + { + PlayAnimation("Gesture, Additive", GroundLight2StateHash, GroundLightParamHash, attackDuration); + PlayAnimation("Gesture, Override", GroundLight2StateHash, GroundLightParamHash, attackDuration); + } + else + { + PlayAnimation("FullBody, Override", GroundLight2StateHash, GroundLightParamHash, attackDuration); + } + slashChildName = "GroundLight2Slash"; + swingEffectPrefab = comboSwingEffectPrefab; + hitEffectPrefab = comboHitEffectPrefab; + attackSoundString = comboAttackSoundString; + break; + case ComboState.GroundLight3: + attackDuration = baseFinisherAttackDuration / attackSpeedStat; + overlapAttack = InitMeleeOverlap(finisherDamageCoefficient, hitEffectPrefab, GetModelTransform(), "SwordLarge"); + if (@bool || !bool2) + { + PlayAnimation("Gesture, Additive", GroundLight3StateHash, GroundLightParamHash, attackDuration); + PlayAnimation("Gesture, Override", GroundLight3StateHash, GroundLightParamHash, attackDuration); + } + else + { + PlayAnimation("FullBody, Override", GroundLight3StateHash, GroundLightParamHash, attackDuration); + } + slashChildName = "GroundLight3Slash"; + swingEffectPrefab = finisherSwingEffectPrefab; + hitEffectPrefab = finisherHitEffectPrefab; + attackSoundString = finisherAttackSoundString; + break; + } + base.characterBody.SetAimTimer(attackDuration + 1f); + overlapAttack.hitEffectPrefab = hitEffectPrefab; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + hitPauseTimer -= GetDeltaTime(); + if (base.isAuthority) + { + bool flag = FireMeleeOverlap(overlapAttack, animator, "Sword.active", forceMagnitude); + hasHit |= flag; + if (flag) + { + Util.PlaySound(hitSoundString, base.gameObject); + if (!isInHitPause) + { + hitStopCachedState = CreateHitStopCachedState(base.characterMotor, animator, "GroundLight.playbackRate"); + hitPauseTimer = hitPauseDuration / attackSpeedStat; + isInHitPause = true; + } + } + if (hitPauseTimer <= 0f && isInHitPause) + { + ConsumeHitStopCachedState(hitStopCachedState, base.characterMotor, animator); + isInHitPause = false; + } + } + if (animator.GetFloat(SwordactiveParamHash) > 0f && !hasSwung) + { + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, slashPitch); + HealthComponent healthComponent = base.characterBody.healthComponent; + CharacterDirection component = base.characterBody.GetComponent(); + if ((bool)healthComponent) + { + healthComponent.TakeDamageForce(selfForceMagnitude * component.forward, alwaysApply: true); + } + hasSwung = true; + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, slashChildName, transmit: false); + } + if (!isInHitPause) + { + stopwatch += GetDeltaTime(); + } + else + { + base.characterMotor.velocity = Vector3.zero; + animator.SetFloat(GroundLightParamHash, 0f); + } + if (base.isAuthority && stopwatch >= attackDuration - earlyExitDuration) + { + if (!hasSwung) + { + overlapAttack.Fire(); + } + if (base.inputBank.skill1.down && comboState != ComboState.GroundLight3) + { + GroundLight groundLight = new GroundLight(); + groundLight.comboState = comboState + 1; + outer.SetNextState(groundLight); + } + else if (stopwatch >= attackDuration) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)comboState); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + comboState = (ComboState)reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/PrepAssaulter2.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/PrepAssaulter2.cs new file mode 100644 index 0000000..da008e4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/PrepAssaulter2.cs @@ -0,0 +1,71 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Merc; + +public class PrepAssaulter2 : BaseState +{ + public static float baseDuration; + + public static float smallHopVelocity; + + public static string enterSoundString; + + private float duration; + + private static int AssaulterPrepStateHash = Animator.StringToHash("AssaulterPrep"); + + private static int AssaulterPrepParamHash = Animator.StringToHash("AssaulterPrep.playbackRate"); + + public int dashIndex { private get; set; } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("FullBody, Override", AssaulterPrepStateHash, AssaulterPrepParamHash, baseDuration); + FindModelChild("PreDashEffect").gameObject.SetActive(value: true); + Util.PlaySound(enterSoundString, base.gameObject); + Ray aimRay = GetAimRay(); + base.characterDirection.forward = aimRay.direction; + base.characterDirection.moveVector = aimRay.direction; + SmallHop(base.characterMotor, smallHopVelocity); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, 0.2f); + } + FindModelChild("PreDashEffect").gameObject.SetActive(value: false); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new Assaulter2()); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)dashIndex); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dashIndex = reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/Uppercut.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/Uppercut.cs new file mode 100644 index 0000000..aac4da2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/Uppercut.cs @@ -0,0 +1,144 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Merc; + +public class Uppercut : BaseState +{ + public static GameObject swingEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static string enterSoundString; + + public static string attackSoundString; + + public static string hitSoundString; + + public static float slashPitch; + + public static float hitPauseDuration; + + public static float upwardForceStrength; + + public static float baseDuration; + + public static float baseDamageCoefficient; + + public static string slashChildName; + + public static float moveSpeedBonusCoefficient; + + public static string hitboxString; + + public static AnimationCurve yVelocityCurve; + + protected Animator animator; + + protected float duration; + + protected float hitInterval; + + protected bool hasSwung; + + protected float hitPauseTimer; + + protected bool isInHitPause; + + protected OverlapAttack overlapAttack; + + protected HitStopCachedState hitStopCachedState; + + private static int UppercutExitStateHash = Animator.StringToHash("UppercutExit"); + + private static int UppercutStateHash = Animator.StringToHash("Uppercut"); + + private static int UppercutParamHash = Animator.StringToHash("Uppercut.playbackRate"); + + private static int SwordactiveParamHash = Animator.StringToHash("Sword.active"); + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + duration = baseDuration / attackSpeedStat; + overlapAttack = InitMeleeOverlap(baseDamageCoefficient, hitEffectPrefab, GetModelTransform(), hitboxString); + overlapAttack.forceVector = Vector3.up * upwardForceStrength; + if ((bool)base.characterDirection && (bool)base.inputBank) + { + base.characterDirection.forward = base.inputBank.aimDirection; + } + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnim(); + } + + protected virtual void PlayAnim() + { + PlayCrossfade("FullBody, Override", UppercutStateHash, UppercutParamHash, duration, 0.1f); + } + + public override void OnExit() + { + base.OnExit(); + PlayAnimation("FullBody, Override", UppercutExitStateHash); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + hitPauseTimer -= deltaTime; + if (!base.isAuthority) + { + return; + } + if (animator.GetFloat(SwordactiveParamHash) > 0.2f && !hasSwung) + { + hasSwung = true; + base.characterMotor.Motor.ForceUnground(); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, slashPitch); + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, slashChildName, transmit: true); + } + if (FireMeleeOverlap(overlapAttack, animator, SwordactiveParamHash, 0f, calculateForceVector: false)) + { + Util.PlaySound(hitSoundString, base.gameObject); + if (!isInHitPause) + { + hitStopCachedState = CreateHitStopCachedState(base.characterMotor, animator, "Uppercut.playbackRate"); + hitPauseTimer = hitPauseDuration / attackSpeedStat; + isInHitPause = true; + } + } + if (hitPauseTimer <= 0f && isInHitPause) + { + ConsumeHitStopCachedState(hitStopCachedState, base.characterMotor, animator); + base.characterMotor.Motor.ForceUnground(); + isInHitPause = false; + } + if (!isInHitPause) + { + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + Vector3 velocity = base.characterDirection.forward * moveSpeedStat * Mathf.Lerp(moveSpeedBonusCoefficient, 0f, base.age / duration); + velocity.y = yVelocityCurve.Evaluate(base.fixedAge / duration); + base.characterMotor.velocity = velocity; + } + } + else + { + base.fixedAge -= deltaTime; + base.characterMotor.velocity = Vector3.zero; + hitPauseTimer -= deltaTime; + animator.SetFloat(UppercutParamHash, 0f); + } + if (base.fixedAge >= duration) + { + if (hasSwung) + { + hasSwung = true; + overlapAttack.Fire(); + } + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindAir.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindAir.cs new file mode 100644 index 0000000..10b56fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindAir.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace EntityStates.Merc; + +public class WhirlwindAir : WhirlwindBase +{ + private static int WhirlwindAirExitStateHash = Animator.StringToHash("WhirlwindAirExit"); + + private static int WhirlwindAirStateHash = Animator.StringToHash("WhirlwindAir"); + + private static int WhirlwindParamHash = Animator.StringToHash("Whirlwind.playbackRate"); + + protected override void PlayAnim() + { + PlayCrossfade("FullBody, Override", WhirlwindAirStateHash, WhirlwindParamHash, duration, 0.1f); + } + + public override void OnExit() + { + base.OnExit(); + PlayAnimation("FullBody, Override", WhirlwindAirExitStateHash); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindBase.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindBase.cs new file mode 100644 index 0000000..ea09600 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindBase.cs @@ -0,0 +1,146 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Merc; + +public class WhirlwindBase : BaseState +{ + public static GameObject swingEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static string attackSoundString; + + public static string hitSoundString; + + public static float slashPitch; + + public static float hitPauseDuration; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float baseDamageCoefficient; + + [SerializeField] + public string slashChildName; + + [SerializeField] + public float selfForceMagnitude; + + [SerializeField] + public float moveSpeedBonusCoefficient; + + [SerializeField] + public float smallHopVelocity; + + [SerializeField] + public string hitboxString; + + protected Animator animator; + + protected float duration; + + protected float hitInterval; + + protected int swingCount; + + protected float hitPauseTimer; + + protected bool isInHitPause; + + protected OverlapAttack overlapAttack; + + protected HitStopCachedState hitStopCachedState; + + private static int SwordactiveParamHash = Animator.StringToHash("Sword.active"); + + private static int WhirlwindplaybackRateParamHash = Animator.StringToHash("Whirlwind.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + duration = baseDuration / attackSpeedStat; + overlapAttack = InitMeleeOverlap(baseDamageCoefficient, hitEffectPrefab, GetModelTransform(), hitboxString); + if ((bool)base.characterDirection && (bool)base.inputBank) + { + base.characterDirection.forward = base.inputBank.aimDirection; + } + SmallHop(base.characterMotor, smallHopVelocity); + PlayAnim(); + } + + protected virtual void PlayAnim() + { + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + hitPauseTimer -= GetDeltaTime(); + if (animator.GetFloat("Sword.active") > (float)swingCount) + { + swingCount++; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, slashPitch); + EffectManager.SimpleMuzzleFlash(swingEffectPrefab, base.gameObject, slashChildName, transmit: false); + if (base.isAuthority) + { + overlapAttack.ResetIgnoredHealthComponents(); + if ((bool)base.characterMotor) + { + base.characterMotor.ApplyForce(selfForceMagnitude * base.characterDirection.forward, alwaysApply: true); + } + } + } + if (!base.isAuthority) + { + return; + } + if (FireMeleeOverlap(overlapAttack, animator, SwordactiveParamHash, 0f)) + { + Util.PlaySound(hitSoundString, base.gameObject); + if (!isInHitPause) + { + hitStopCachedState = CreateHitStopCachedState(base.characterMotor, animator, "Whirlwind.playbackRate"); + hitPauseTimer = hitPauseDuration / attackSpeedStat; + isInHitPause = true; + } + } + if (hitPauseTimer <= 0f && isInHitPause) + { + ConsumeHitStopCachedState(hitStopCachedState, base.characterMotor, animator); + isInHitPause = false; + } + if (!isInHitPause) + { + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + Vector3 velocity = base.characterDirection.forward * moveSpeedStat * Mathf.Lerp(moveSpeedBonusCoefficient, 1f, base.age / duration); + velocity.y = base.characterMotor.velocity.y; + base.characterMotor.velocity = velocity; + } + } + else + { + base.characterMotor.velocity = Vector3.zero; + hitPauseTimer -= GetDeltaTime(); + animator.SetFloat(WhirlwindplaybackRateParamHash, 0f); + } + if (base.fixedAge >= duration) + { + while (swingCount < 2) + { + swingCount++; + overlapAttack.Fire(); + } + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindEntry.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindEntry.cs new file mode 100644 index 0000000..35c4365 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindEntry.cs @@ -0,0 +1,14 @@ +namespace EntityStates.Merc; + +public class WhirlwindEntry : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + EntityState nextState = (((bool)base.characterMotor && base.characterMotor.isGrounded) ? ((WhirlwindBase)new WhirlwindGround()) : ((WhirlwindBase)new WhirlwindAir())); + outer.SetNextState(nextState); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindGround.cs b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindGround.cs new file mode 100644 index 0000000..a5fa6a8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Merc/WhirlwindGround.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +namespace EntityStates.Merc; + +public class WhirlwindGround : WhirlwindBase +{ + private static int WhirlwindGroundStateHash = Animator.StringToHash("WhirlwindGround"); + + private static int LightImpactStateHash = Animator.StringToHash("LightImpact"); + + private static int WhirlwindParamHash = Animator.StringToHash("Whirlwind.playbackRate"); + + protected override void PlayAnim() + { + PlayCrossfade("FullBody, Override", WhirlwindGroundStateHash, WhirlwindParamHash, duration, 0.1f); + } + + public override void OnExit() + { + base.OnExit(); + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 3f); + PlayAnimation("Impact", LightImpactStateHash); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/InPlant.cs b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/InPlant.cs new file mode 100644 index 0000000..77ca59c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/InPlant.cs @@ -0,0 +1,50 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MiniMushroom; + +public class InPlant : BaseState +{ + public static GameObject burrowPrefab; + + public static float baseDuration; + + public static string burrowInSoundString; + + private float duration; + + private static int PlantStartStateHash = Animator.StringToHash("PlantStart"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int PlantStartParamHash = Animator.StringToHash("PlantStart.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(burrowInSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + PlayAnimation("Plant", PlantStartStateHash, PlantStartParamHash, duration); + } + + public override void OnExit() + { + PlayAnimation("Plant", EmptyStateHash); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new Plant()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/Plant.cs b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/Plant.cs new file mode 100644 index 0000000..7170152 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/Plant.cs @@ -0,0 +1,79 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MiniMushroom; + +public class Plant : BaseState +{ + public static float healFraction; + + public static float baseMaxDuration; + + public static float baseMinDuration; + + public static float mushroomRadius; + + public static string healSoundLoop; + + public static string healSoundStop; + + private float maxDuration; + + private float minDuration; + + private GameObject mushroomWard; + + private uint soundID; + + private static int PlantLoopStateHash = Animator.StringToHash("PlantLoop"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Plant", PlantLoopStateHash); + maxDuration = baseMaxDuration / attackSpeedStat; + minDuration = baseMinDuration / attackSpeedStat; + soundID = Util.PlaySound(healSoundLoop, base.characterBody.modelLocator.modelTransform.gameObject); + if (NetworkServer.active && mushroomWard == null) + { + mushroomWard = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/MiniMushroomWard"), base.characterBody.footPosition, Quaternion.identity); + mushroomWard.GetComponent().teamIndex = base.teamComponent.teamIndex; + if ((bool)mushroomWard) + { + HealingWard component = mushroomWard.GetComponent(); + component.healFraction = healFraction; + component.healPoints = 0f; + component.Networkradius = mushroomRadius; + } + NetworkServer.Spawn(mushroomWard); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + bool flag = base.inputBank.moveVector.sqrMagnitude > 0.1f; + if (base.fixedAge > maxDuration || (base.fixedAge > minDuration && flag)) + { + outer.SetNextState(new UnPlant()); + } + } + } + + public override void OnExit() + { + PlayAnimation("Plant", EmptyStateHash); + AkSoundEngine.StopPlayingID(soundID); + Util.PlaySound(healSoundStop, base.gameObject); + if ((bool)mushroomWard) + { + EntityState.Destroy(mushroomWard); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/SpawnState.cs new file mode 100644 index 0000000..22d494b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/SpawnState.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MiniMushroom; + +public class SpawnState : BaseState +{ + public static GameObject burrowPrefab; + + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/SporeGrenade.cs b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/SporeGrenade.cs new file mode 100644 index 0000000..9557456 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/SporeGrenade.cs @@ -0,0 +1,168 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.MiniMushroom; + +public class SporeGrenade : BaseState +{ + public static GameObject chargeEffectPrefab; + + public static string attackSoundString; + + public static string chargeUpSoundString; + + public static float recoilAmplitude = 1f; + + public static GameObject projectilePrefab; + + public static float baseDuration = 2f; + + public static string muzzleString; + + public static float damageCoefficient; + + public static float timeToTarget = 3f; + + public static float projectileVelocity = 55f; + + public static float minimumDistance; + + public static float maximumDistance; + + public static float baseChargeTime = 2f; + + private uint chargeupSoundID; + + private Ray projectileRay; + + private Transform modelTransform; + + private float duration; + + private float chargeTime; + + private bool hasFired; + + private Animator modelAnimator; + + private GameObject chargeEffectInstance; + + private static int ChargeStateHash = Animator.StringToHash("Charge"); + + private static int isChargedParamHash = Animator.StringToHash("isCharged"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + chargeTime = baseChargeTime / attackSpeedStat; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(isChargedParamHash, value: false); + PlayAnimation("Gesture, Additive", ChargeStateHash); + chargeupSoundID = Util.PlaySound(chargeUpSoundString, base.characterBody.modelLocator.modelTransform.gameObject); + } + Transform transform = FindModelChild("ChargeSpot"); + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!(base.fixedAge >= chargeTime)) + { + return; + } + if (!hasFired) + { + hasFired = true; + modelAnimator?.SetBool(isChargedParamHash, value: true); + if (base.isAuthority) + { + FireGrenade(muzzleString); + } + } + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + PlayAnimation("Gesture, Additive", EmptyStateHash); + AkSoundEngine.StopPlayingID(chargeupSoundID); + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + base.OnExit(); + } + + private void FireGrenade(string targetMuzzle) + { + Ray aimRay = GetAimRay(); + Ray ray = new Ray(aimRay.origin, Vector3.up); + Transform transform = FindModelChild(targetMuzzle); + if ((bool)transform) + { + ray.origin = transform.position; + } + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + bool flag = false; + Vector3 vector = Vector3.zero; + RaycastHit hitInfo; + if ((bool)hurtBox) + { + vector = hurtBox.transform.position; + flag = true; + } + else if (Physics.Raycast(aimRay, out hitInfo, 1000f, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + vector = hitInfo.point; + flag = true; + } + float magnitude = projectileVelocity; + if (flag) + { + Vector3 vector2 = vector - ray.origin; + Vector2 vector3 = new Vector2(vector2.x, vector2.z); + float magnitude2 = vector3.magnitude; + Vector2 vector4 = vector3 / magnitude2; + if (magnitude2 < minimumDistance) + { + magnitude2 = minimumDistance; + } + if (magnitude2 > maximumDistance) + { + magnitude2 = maximumDistance; + } + float y = Trajectory.CalculateInitialYSpeed(timeToTarget, vector2.y); + float num = magnitude2 / timeToTarget; + Vector3 direction = new Vector3(vector4.x * num, y, vector4.y * num); + magnitude = direction.magnitude; + ray.direction = direction; + } + Quaternion rotation = Util.QuaternionSafeLookRotation(ray.direction + Random.insideUnitSphere * 0.05f); + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, rotation, base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, magnitude); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/UnPlant.cs b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/UnPlant.cs new file mode 100644 index 0000000..e48e9a2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MiniMushroom/UnPlant.cs @@ -0,0 +1,56 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MiniMushroom; + +public class UnPlant : BaseState +{ + public static GameObject plantEffectPrefab; + + public static float baseDuration; + + public static string UnplantOutSoundString; + + private float stopwatch; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private float duration; + + private static int PlantEndStateHash = Animator.StringToHash("PlantEnd"); + + private static int PlantEndParamHash = Animator.StringToHash("PlantEnd.playbackRate"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + EffectManager.SimpleMuzzleFlash(plantEffectPrefab, base.gameObject, "BurrowCenter", transmit: false); + Util.PlaySound(UnplantOutSoundString, base.gameObject); + PlayAnimation("Plant", PlantEndStateHash, PlantEndParamHash, duration); + } + + public override void OnExit() + { + PlayAnimation("Plant, Additive", EmptyStateHash); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct.Weapon/ChargeConstructBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct.Weapon/ChargeConstructBeam.cs new file mode 100644 index 0000000..7ebec87 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct.Weapon/ChargeConstructBeam.cs @@ -0,0 +1,88 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MinorConstruct.Weapon; + +public class ChargeConstructBeam : BaseState +{ + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string exitSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string chargeEffectMuzzle; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public float baseDuration; + + private float duration; + + private GameObject chargeInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + Transform transform = FindModelChild(chargeEffectMuzzle); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance.transform.parent = base.gameObject.transform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void Update() + { + base.Update(); + if ((bool)chargeInstance) + { + Ray aimRay = GetAimRay(); + chargeInstance.transform.forward = aimRay.direction; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new FireConstructBeam()); + } + } + + public override void OnExit() + { + Util.PlaySound(exitSoundString, base.gameObject); + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct.Weapon/FireConstructBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct.Weapon/FireConstructBeam.cs new file mode 100644 index 0000000..54ad17c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct.Weapon/FireConstructBeam.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace EntityStates.MinorConstruct.Weapon; + +public class FireConstructBeam : GenericProjectileBaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/BaseHideState.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/BaseHideState.cs new file mode 100644 index 0000000..995ea5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/BaseHideState.cs @@ -0,0 +1,41 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MinorConstruct; + +public class BaseHideState : BaseState +{ + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string childToEnable; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + Transform transform = FindModelChild(childToEnable); + if ((bool)transform) + { + transform.gameObject.SetActive(value: true); + } + } + + public override void OnExit() + { + Transform transform = FindModelChild(childToEnable); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/DeathState.cs new file mode 100644 index 0000000..8e28bda --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/DeathState.cs @@ -0,0 +1,26 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MinorConstruct; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject explosionPrefab; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + EffectManager.SimpleEffect(explosionPrefab, base.transform.position, base.transform.rotation, transmit: true); + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/FindSurface.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/FindSurface.cs new file mode 100644 index 0000000..78fa5e8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/FindSurface.cs @@ -0,0 +1,31 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MinorConstruct; + +public class FindSurface : NoCastSpawn +{ + [SerializeField] + public int raycastCount; + + [SerializeField] + public float maxRaycastLength; + + public override void OnEnter() + { + RaycastHit hitInfo = default(RaycastHit); + Vector3 corePosition = base.characterBody.corePosition; + if (base.isAuthority && !(base.characterBody.master.minionOwnership?.ownerMaster)) + { + for (int i = 0; i < raycastCount; i++) + { + if (Physics.Raycast(corePosition, Random.onUnitSphere, out hitInfo, maxRaycastLength, LayerIndex.world.mask)) + { + base.transform.position = hitInfo.point; + base.transform.up = hitInfo.normal; + } + } + } + base.OnEnter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/Hidden.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/Hidden.cs new file mode 100644 index 0000000..87b9376 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/Hidden.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MinorConstruct; + +public class Hidden : BaseHideState +{ + [SerializeField] + public BuffDef buffDef; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)buffDef) + { + base.characterBody.AddBuff(buffDef); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.characterBody.outOfCombat || !base.characterBody.outOfDanger) + { + outer.SetNextState(new Revealed()); + } + } + + public override void OnExit() + { + if ((bool)buffDef) + { + base.characterBody.RemoveBuff(buffDef); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/NoCastSpawn.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/NoCastSpawn.cs new file mode 100644 index 0000000..508824d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/NoCastSpawn.cs @@ -0,0 +1,24 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MinorConstruct; + +public class NoCastSpawn : BaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/Revealed.cs b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/Revealed.cs new file mode 100644 index 0000000..121ef14 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MinorConstruct/Revealed.cs @@ -0,0 +1,13 @@ +namespace EntityStates.MinorConstruct; + +public class Revealed : BaseHideState +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.characterBody.outOfCombat && base.characterBody.outOfDanger) + { + outer.SetNextState(new Hidden()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Active.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Active.cs new file mode 100644 index 0000000..b099e41 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Active.cs @@ -0,0 +1,73 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Arena.NullWard; + +public class Active : NullWardBaseState +{ + public static string soundEntryEvent; + + public static string soundLoopStartEvent; + + public static string soundLoopEndEvent; + + private static Run.FixedTimeStamp startTime; + + private HoldoutZoneController holdoutZoneController; + + public override void OnEnter() + { + base.OnEnter(); + holdoutZoneController = GetComponent(); + holdoutZoneController.enabled = true; + holdoutZoneController.baseRadius = NullWardBaseState.wardRadiusOn; + purchaseInteraction.SetAvailable(newAvailable: false); + base.arenaMissionController.rewardSpawnPosition = childLocator.FindChild("RewardSpawn").gameObject; + base.arenaMissionController.monsterSpawnPosition = childLocator.FindChild("MonsterSpawn").gameObject; + childLocator.FindChild("ActiveEffect").gameObject.SetActive(value: true); + if (NetworkServer.active) + { + base.arenaMissionController.BeginRound(); + } + if (base.isAuthority) + { + startTime = Run.FixedTimeStamp.now; + } + Util.PlaySound(soundEntryEvent, base.gameObject); + Util.PlaySound(soundLoopStartEvent, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + sphereZone.Networkradius = holdoutZoneController.currentRadius; + if (base.isAuthority && holdoutZoneController.charge >= 1f) + { + outer.SetNextState(new Complete()); + } + } + + public override void OnExit() + { + if ((bool)holdoutZoneController) + { + holdoutZoneController.enabled = false; + } + Util.PlaySound(soundLoopEndEvent, base.gameObject); + childLocator.FindChild("ActiveEffect").gameObject.SetActive(value: false); + childLocator.FindChild("WardOnEffect").gameObject.SetActive(value: false); + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(startTime); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + startTime = reader.ReadFixedTimeStamp(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Complete.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Complete.cs new file mode 100644 index 0000000..8bd7526 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Complete.cs @@ -0,0 +1,33 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Arena.NullWard; + +public class Complete : NullWardBaseState +{ + public static float duration; + + public static string soundEntryEvent; + + public override void OnEnter() + { + base.OnEnter(); + sphereZone.Networkradius = NullWardBaseState.wardRadiusOn; + purchaseInteraction.SetAvailable(newAvailable: false); + childLocator.FindChild("CompleteEffect").gameObject.SetActive(value: true); + if (NetworkServer.active) + { + base.arenaMissionController.EndRound(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + sphereZone.Networkradius = Mathf.Lerp(NullWardBaseState.wardRadiusOn, NullWardBaseState.wardRadiusOff, base.fixedAge / duration); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new Off()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/NullWardBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/NullWardBaseState.cs new file mode 100644 index 0000000..4e09a5e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/NullWardBaseState.cs @@ -0,0 +1,30 @@ +using RoR2; + +namespace EntityStates.Missions.Arena.NullWard; + +public class NullWardBaseState : EntityState +{ + public static float wardRadiusOff; + + public static float wardRadiusOn; + + public static float wardWaitingRadius; + + protected SphereZone sphereZone; + + protected PurchaseInteraction purchaseInteraction; + + protected ChildLocator childLocator; + + protected ArenaMissionController arenaMissionController => ArenaMissionController.instance; + + public override void OnEnter() + { + base.OnEnter(); + sphereZone = GetComponent(); + sphereZone.enabled = true; + purchaseInteraction = GetComponent(); + childLocator = GetComponent(); + base.gameObject.GetComponent().teamIndex = TeamIndex.Player; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Off.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Off.cs new file mode 100644 index 0000000..c6f2d48 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/Off.cs @@ -0,0 +1,12 @@ +namespace EntityStates.Missions.Arena.NullWard; + +public class Off : NullWardBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + sphereZone.Networkradius = NullWardBaseState.wardRadiusOff; + purchaseInteraction.SetAvailable(newAvailable: false); + sphereZone.enabled = false; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/WardOnAndReady.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/WardOnAndReady.cs new file mode 100644 index 0000000..6a58840 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Arena.NullWard/WardOnAndReady.cs @@ -0,0 +1,26 @@ +using RoR2; + +namespace EntityStates.Missions.Arena.NullWard; + +public class WardOnAndReady : NullWardBaseState +{ + public static string soundLoopStartEvent; + + public static string soundLoopEndEvent; + + public override void OnEnter() + { + base.OnEnter(); + sphereZone.Networkradius = NullWardBaseState.wardWaitingRadius; + purchaseInteraction.SetAvailable(newAvailable: true); + childLocator.FindChild("WardOnEffect").gameObject.SetActive(value: true); + sphereZone.enabled = true; + Util.PlaySound(soundLoopStartEvent, base.gameObject); + } + + public override void OnExit() + { + Util.PlaySound(soundLoopEndEvent, base.gameObject); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial.cs new file mode 100644 index 0000000..28d7c35 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial.cs @@ -0,0 +1,33 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class AfterTrial : ArtifactTrialControllerBaseState +{ + public virtual Type GetNextStateType() + { + return typeof(FinishTrial); + } + + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction.enabled = true; + childLocator.FindChild("AfterTrial").gameObject.SetActive(value: true); + outer.mainStateType = new SerializableEntityStateType(GetNextStateType()); + Highlight component = GetComponent(); + Transform transform = childLocator.FindChild("CompletedArtifactMesh"); + if ((bool)component && (bool)transform) + { + component.targetRenderer = transform.GetComponent(); + } + } + + public override void OnExit() + { + childLocator.FindChild("AfterTrial").gameObject.SetActive(value: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial1.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial1.cs new file mode 100644 index 0000000..ded3ffe --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial1.cs @@ -0,0 +1,11 @@ +using System; + +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class AfterTrial1 : AfterTrial +{ + public override Type GetNextStateType() + { + return typeof(FinishTrial1); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial2.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial2.cs new file mode 100644 index 0000000..58a3c85 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/AfterTrial2.cs @@ -0,0 +1,11 @@ +using System; + +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class AfterTrial2 : AfterTrial +{ + public override Type GetNextStateType() + { + return typeof(FinishTrial2); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/ArtifactTrialControllerBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/ArtifactTrialControllerBaseState.cs new file mode 100644 index 0000000..ab1f675 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/ArtifactTrialControllerBaseState.cs @@ -0,0 +1,17 @@ +using RoR2; + +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class ArtifactTrialControllerBaseState : EntityState +{ + protected PurchaseInteraction purchaseInteraction; + + protected ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction = GetComponent(); + childLocator = GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/BeforeTrial.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/BeforeTrial.cs new file mode 100644 index 0000000..6181dce --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/BeforeTrial.cs @@ -0,0 +1,17 @@ +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class BeforeTrial : ArtifactTrialControllerBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction.enabled = true; + childLocator.FindChild("BeforeTrial").gameObject.SetActive(value: true); + } + + public override void OnExit() + { + childLocator.FindChild("BeforeTrial").gameObject.SetActive(value: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/BeforeTrial1.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/BeforeTrial1.cs new file mode 100644 index 0000000..275be9c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/BeforeTrial1.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class BeforeTrial1 : BeforeTrial +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/DuringTrial.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/DuringTrial.cs new file mode 100644 index 0000000..9891bff --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/DuringTrial.cs @@ -0,0 +1,22 @@ +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class DuringTrial : ArtifactTrialControllerBaseState +{ + public virtual EntityState GetNextState() + { + return new AfterTrial(); + } + + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction.enabled = false; + childLocator.FindChild("DuringTrial").gameObject.SetActive(value: true); + } + + public override void OnExit() + { + childLocator.FindChild("DuringTrial").gameObject.SetActive(value: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/DuringTrial1.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/DuringTrial1.cs new file mode 100644 index 0000000..30bae88 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/DuringTrial1.cs @@ -0,0 +1,20 @@ +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class DuringTrial1 : DuringTrial +{ + public static float trialDuration; + + public override EntityState GetNextState() + { + return new AfterTrial1(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= trialDuration) + { + outer.SetNextState(GetNextState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial.cs new file mode 100644 index 0000000..7cd031f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class FinishTrial : ArtifactTrialControllerBaseState +{ + [SerializeField] + public string achievementName; + + public override void OnEnter() + { + base.OnEnter(); + childLocator.FindChild("FinishTrial").gameObject.SetActive(value: true); + AchievementDef achievementDef = AchievementManager.GetAchievementDef(achievementName); + if (achievementDef == null) + { + return; + } + foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList) + { + AchievementManager.GetUserAchievementManager(readOnlyLocalUsers).GrantAchievement(achievementDef); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial1.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial1.cs new file mode 100644 index 0000000..c2ec810 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial1.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class FinishTrial1 : FinishTrial +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial2.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial2.cs new file mode 100644 index 0000000..158a29d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.ArtifactWorld.TrialController/FinishTrial2.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Missions.ArtifactWorld.TrialController; + +public class FinishTrial2 : FinishTrial +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BossDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BossDeath.cs new file mode 100644 index 0000000..0c47220 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BossDeath.cs @@ -0,0 +1,20 @@ +using UnityEngine.Networking; + +namespace EntityStates.Missions.BrotherEncounter; + +public class BossDeath : BrotherEncounterBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + outer.SetNextState(new EncounterFinished()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BrotherEncounterBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BrotherEncounterBaseState.cs new file mode 100644 index 0000000..cf4901b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BrotherEncounterBaseState.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.BrotherEncounter; + +public class BrotherEncounterBaseState : EntityState +{ + protected ChildLocator childLocator; + + protected virtual bool shouldEnableArenaWalls => true; + + protected virtual bool shouldEnableArenaNodes => true; + + public override void OnEnter() + { + base.OnEnter(); + childLocator = GetComponent(); + Transform transform = childLocator.FindChild("ArenaWalls"); + Transform transform2 = childLocator.FindChild("ArenaNodes"); + if ((bool)transform) + { + transform.gameObject.SetActive(shouldEnableArenaWalls); + } + if ((bool)transform2) + { + transform2.gameObject.SetActive(shouldEnableArenaNodes); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public void KillAllMonsters() + { + if (!NetworkServer.active) + { + return; + } + foreach (TeamComponent item in new List(TeamComponent.GetTeamMembers(TeamIndex.Monster))) + { + if ((bool)item) + { + HealthComponent component = item.GetComponent(); + if ((bool)component) + { + component.Suicide(); + } + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BrotherEncounterPhaseBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BrotherEncounterPhaseBaseState.cs new file mode 100644 index 0000000..134a34e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/BrotherEncounterPhaseBaseState.cs @@ -0,0 +1,132 @@ +using RoR2; +using RoR2.CharacterSpeech; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.BrotherEncounter; + +public abstract class BrotherEncounterPhaseBaseState : BrotherEncounterBaseState +{ + [SerializeField] + public float durationBeforeEnablingCombatEncounter; + + [SerializeField] + public GameObject speechControllerPrefab; + + protected ScriptedCombatEncounter phaseScriptedCombatEncounter; + + protected GameObject phaseControllerObject; + + protected GameObject phaseControllerSubObjectContainer; + + protected BossGroup phaseBossGroup; + + private bool hasSpawned; + + private bool finishedServer; + + private const float minimumDurationPerPhase = 2f; + + private Run.FixedTimeStamp healthBarShowTime = Run.FixedTimeStamp.positiveInfinity; + + protected abstract EntityState nextState { get; } + + protected abstract string phaseControllerChildString { get; } + + protected virtual float healthBarShowDelay => 0f; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)PhaseCounter.instance) + { + PhaseCounter.instance.GoToNextPhase(); + } + if ((bool)childLocator) + { + phaseControllerObject = childLocator.FindChild(phaseControllerChildString).gameObject; + if ((bool)phaseControllerObject) + { + phaseScriptedCombatEncounter = phaseControllerObject.GetComponent(); + phaseBossGroup = phaseControllerObject.GetComponent(); + phaseControllerSubObjectContainer = phaseControllerObject.transform.Find("PhaseObjects").gameObject; + phaseControllerSubObjectContainer.SetActive(value: true); + } + GameObject gameObject = childLocator.FindChild("AllPhases").gameObject; + if ((bool)gameObject) + { + gameObject.SetActive(value: true); + } + } + healthBarShowTime = Run.FixedTimeStamp.now + healthBarShowDelay; + if ((bool)DirectorCore.instance) + { + CombatDirector[] components = DirectorCore.instance.GetComponents(); + for (int i = 0; i < components.Length; i++) + { + components[i].enabled = false; + } + } + if (NetworkServer.active && (object)phaseScriptedCombatEncounter != null) + { + phaseScriptedCombatEncounter.combatSquad.onMemberAddedServer += OnMemberAddedServer; + } + } + + public override void OnExit() + { + if ((object)phaseScriptedCombatEncounter != null) + { + phaseScriptedCombatEncounter.combatSquad.onMemberAddedServer -= OnMemberAddedServer; + } + if ((bool)phaseControllerSubObjectContainer) + { + phaseControllerSubObjectContainer.SetActive(value: false); + } + if ((bool)phaseBossGroup) + { + phaseBossGroup.shouldDisplayHealthBarOnHud = false; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + phaseBossGroup.shouldDisplayHealthBarOnHud = healthBarShowTime.hasPassed; + if (!hasSpawned) + { + if (base.fixedAge > durationBeforeEnablingCombatEncounter) + { + BeginEncounter(); + } + } + else if (NetworkServer.active && !finishedServer && base.fixedAge > 2f + durationBeforeEnablingCombatEncounter && (bool)phaseScriptedCombatEncounter && phaseScriptedCombatEncounter.combatSquad.memberCount == 0) + { + finishedServer = true; + outer.SetNextState(nextState); + } + } + + protected void BeginEncounter() + { + hasSpawned = true; + PreEncounterBegin(); + if (NetworkServer.active) + { + phaseScriptedCombatEncounter.BeginEncounter(); + } + } + + protected virtual void PreEncounterBegin() + { + } + + protected virtual void OnMemberAddedServer(CharacterMaster master) + { + if ((bool)speechControllerPrefab) + { + Object.Instantiate(speechControllerPrefab, master.transform).GetComponent().characterMaster = master; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/EncounterFinished.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/EncounterFinished.cs new file mode 100644 index 0000000..5b2a766 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/EncounterFinished.cs @@ -0,0 +1,11 @@ +namespace EntityStates.Missions.BrotherEncounter; + +public class EncounterFinished : BrotherEncounterBaseState +{ + protected override bool shouldEnableArenaNodes => false; + + public override void OnEnter() + { + base.OnEnter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase1.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase1.cs new file mode 100644 index 0000000..e90cc05 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase1.cs @@ -0,0 +1,52 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Missions.BrotherEncounter; + +public class Phase1 : BrotherEncounterPhaseBaseState +{ + public static string prespawnSoundString; + + public static float prespawnSoundDelay; + + public static GameObject centerOrbDestroyEffect; + + private bool hasPlayedPrespawnSound; + + protected override string phaseControllerChildString => "Phase1"; + + protected override EntityState nextState => new Phase2(); + + public override void OnEnter() + { + KillAllMonsters(); + base.OnEnter(); + } + + protected override void PreEncounterBegin() + { + base.PreEncounterBegin(); + Transform transform = childLocator.FindChild("CenterOrbEffect"); + transform.gameObject.SetActive(value: false); + EffectManager.SpawnEffect(centerOrbDestroyEffect, new EffectData + { + origin = transform.transform.position + }, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!hasPlayedPrespawnSound && base.fixedAge > prespawnSoundDelay) + { + Transform transform = childLocator.FindChild("CenterOrbEffect"); + Util.PlaySound(prespawnSoundString, transform.gameObject); + hasPlayedPrespawnSound = true; + } + } + + protected override void OnMemberAddedServer(CharacterMaster master) + { + base.OnMemberAddedServer(master); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase2.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase2.cs new file mode 100644 index 0000000..ed7d54b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase2.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace EntityStates.Missions.BrotherEncounter; + +public class Phase2 : BrotherEncounterPhaseBaseState +{ + public static float delayBetweenPillarActivation; + + private List pillarsToActive = new List(); + + private float pillarActivationStopwatch; + + protected override string phaseControllerChildString => "Phase2"; + + protected override EntityState nextState => new Phase3(); + + public override void OnEnter() + { + base.OnEnter(); + GameObject gameObject = childLocator.FindChild("BlockingPillars").gameObject; + if ((bool)gameObject) + { + gameObject.SetActive(value: true); + for (int i = 0; i < gameObject.transform.childCount; i++) + { + pillarsToActive.Add(gameObject.transform.GetChild(i).gameObject); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + pillarActivationStopwatch += GetDeltaTime(); + if (pillarsToActive.Count > 0 && pillarActivationStopwatch > delayBetweenPillarActivation) + { + pillarActivationStopwatch = 0f; + pillarsToActive[0].SetActive(value: true); + pillarsToActive.RemoveAt(0); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase3.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase3.cs new file mode 100644 index 0000000..33982c8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase3.cs @@ -0,0 +1,40 @@ +using EntityStates.BrotherMonster; +using RoR2; + +namespace EntityStates.Missions.BrotherEncounter; + +public class Phase3 : BrotherEncounterPhaseBaseState +{ + protected override string phaseControllerChildString => "Phase3"; + + protected override EntityState nextState => new Phase4(); + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void OnExit() + { + KillAllMonsters(); + base.OnExit(); + } + + protected override void OnMemberAddedServer(CharacterMaster master) + { + base.OnMemberAddedServer(master); + if (!master.hasBody) + { + return; + } + CharacterBody body = master.GetBody(); + if ((bool)body) + { + CharacterDeathBehavior component = body.GetComponent(); + if ((bool)component) + { + component.deathState = new SerializableEntityStateType(typeof(InstantDeathState)); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase4.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase4.cs new file mode 100644 index 0000000..8d3f89f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/Phase4.cs @@ -0,0 +1,16 @@ +namespace EntityStates.Missions.BrotherEncounter; + +public class Phase4 : BrotherEncounterPhaseBaseState +{ + protected override string phaseControllerChildString => "Phase4"; + + protected override EntityState nextState => new BossDeath(); + + protected override float healthBarShowDelay => 6f; + + public override void OnEnter() + { + base.OnEnter(); + BeginEncounter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/PreEncounter.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/PreEncounter.cs new file mode 100644 index 0000000..397e3f7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.BrotherEncounter/PreEncounter.cs @@ -0,0 +1,30 @@ +namespace EntityStates.Missions.BrotherEncounter; + +public class PreEncounter : BaseState +{ + public static float duration; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + childLocator = GetComponent(); + childLocator.FindChild("PreEncounter").gameObject.SetActive(value: true); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new Phase1()); + } + } + + public override void OnExit() + { + childLocator.FindChild("PreEncounter").gameObject.SetActive(value: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionEntityStates.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionEntityStates.cs new file mode 100644 index 0000000..ed889f3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionEntityStates.cs @@ -0,0 +1,14 @@ +using RoR2; + +namespace EntityStates.Missions.GeodeSecretMission; + +public class GeodeSecretMissionEntityStates : EntityState +{ + protected GeodeSecretMissionController geodeSecretMissionController; + + public override void OnEnter() + { + geodeSecretMissionController = base.gameObject.GetComponent(); + base.OnEnter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionEntryState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionEntryState.cs new file mode 100644 index 0000000..0e2f220 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionEntryState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Missions.GeodeSecretMission; + +public class GeodeSecretMissionEntryState : GeodeSecretMissionEntityStates +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionRewardState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionRewardState.cs new file mode 100644 index 0000000..7687019 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.GeodeSecretMission/GeodeSecretMissionRewardState.cs @@ -0,0 +1,49 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.GeodeSecretMission; + +public class GeodeSecretMissionRewardState : GeodeSecretMissionEntityStates +{ + private Xoroshiro128Plus rng; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong); + DropRewards(); + } + } + + public void DropRewards() + { + int participatingPlayerCount = Run.instance.participatingPlayerCount; + if (participatingPlayerCount > 0 && (bool)base.gameObject && (bool)geodeSecretMissionController.rewardDropTable) + { + int num = geodeSecretMissionController.numberOfRewardsSpawned; + if (geodeSecretMissionController.increaseRewardPerPlayer) + { + num *= participatingPlayerCount; + } + float angle = 360f / (float)num; + Vector3 vector = Quaternion.AngleAxis(Random.Range(0, 360), Vector3.up) * (Vector3.up * 40f + Vector3.forward * 5f); + Quaternion quaternion = Quaternion.AngleAxis(angle, Vector3.up); + Vector3 position = geodeSecretMissionController.rewardSpawnLocation.transform.position; + int num2 = 0; + while (num2 < num) + { + GenericPickupController.CreatePickupInfo pickupInfo = default(GenericPickupController.CreatePickupInfo); + pickupInfo.pickupIndex = PickupCatalog.FindPickupIndex(geodeSecretMissionController.rewardDisplayTier); + pickupInfo.pickerOptions = PickupPickerController.GenerateOptionsFromDropTablePlusForcedStorm(geodeSecretMissionController.numberOfRewardOptions, geodeSecretMissionController.rewardDropTable, geodeSecretMissionController.rewardDropTable, rng); + pickupInfo.rotation = Quaternion.identity; + pickupInfo.prefabOverride = geodeSecretMissionController.rewardPrefab; + PickupDropletController.CreatePickupDroplet(pickupInfo, position, vector); + num2++; + vector = quaternion * vector; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/ActivateBeacons.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/ActivateBeacons.cs new file mode 100644 index 0000000..94820d3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/ActivateBeacons.cs @@ -0,0 +1,34 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Goldshores; + +public class ActivateBeacons : EntityState +{ + public override void OnEnter() + { + base.OnEnter(); + if ((bool)GoldshoresMissionController.instance) + { + GoldshoresMissionController.instance.SpawnBeacons(); + } + } + + public override void OnExit() + { + base.OnExit(); + if (!outer.destroying && (bool)GoldshoresMissionController.instance) + { + GoldshoresMissionController.instance.BeginTransitionIntoBossfight(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)GoldshoresMissionController.instance && GoldshoresMissionController.instance.beaconsActive >= GoldshoresMissionController.instance.beaconsRequiredToSpawnBoss) + { + outer.SetNextState(new GoldshoresBossfight()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/Exit.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/Exit.cs new file mode 100644 index 0000000..a7f36f3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/Exit.cs @@ -0,0 +1,67 @@ +using RoR2; +using RoR2.ExpansionManagement; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Goldshores; + +public class Exit : EntityState +{ + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + GameObject gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/InteractableSpawnCard/iscGoldshoresPortal"), new DirectorPlacementRule + { + maxDistance = float.PositiveInfinity, + minDistance = 10f, + placementMode = DirectorPlacementRule.PlacementMode.NearestNode, + position = base.transform.position, + spawnOnTarget = GoldshoresMissionController.instance.bossSpawnPosition + }, Run.instance.stageRng)); + if ((bool)gameObject) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "PORTAL_GOLDSHORES_OPEN" + }); + gameObject.GetComponent().useRunNextStageScene = true; + } + if ((string.IsNullOrEmpty("FalseSonBossComplete") || !Run.instance.GetEventFlag("FalseSonBossComplete")) && IsValidStormTier() && (bool)DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/InteractableSpawnCard/iscColossusPortal"), new DirectorPlacementRule + { + maxDistance = 30f, + minDistance = 10f, + placementMode = DirectorPlacementRule.PlacementMode.NearestNode, + position = base.transform.position + }, Run.instance.stageRng))) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "PORTAL_STORM_OPEN" + }); + } + for (int num = CombatDirector.instancesList.Count - 1; num >= 0; num--) + { + CombatDirector.instancesList[num].enabled = false; + } + } + } + + private bool IsValidStormTier() + { + Run instance = Run.instance; + int stageOrder = instance.nextStageScene.stageOrder; + ExpansionDef requiredExpansion = GoldshoresMissionController.instance.requiredExpansion; + if (instance.IsExpansionEnabled(requiredExpansion) && (stageOrder == 2 || stageOrder == 3 || stageOrder == 4)) + { + return true; + } + return false; + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/GoldshoresBossfight.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/GoldshoresBossfight.cs new file mode 100644 index 0000000..e37f728 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Goldshores/GoldshoresBossfight.cs @@ -0,0 +1,149 @@ +using System; +using EntityStates.Interactables.GoldBeacon; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Goldshores; + +public class GoldshoresBossfight : EntityState +{ + private GoldshoresMissionController missionController; + + public static float shieldRemovalDuration; + + public static GameObject shieldRemovalEffectPrefab; + + public static GameObject shieldRegenerationEffectPrefab; + + public static GameObject combatEncounterPrefab; + + private static float transitionDuration = 3f; + + private bool hasSpawnedBoss; + + private int serverCycleCount; + + private Run.FixedTimeStamp bossInvulnerabilityStartTime; + + private ScriptedCombatEncounter scriptedCombatEncounter; + + private bool bossImmunity; + + private bool bossShouldBeInvulnerable => missionController.beaconsActive < missionController.beaconsToSpawnOnMap; + + public static event Action onOneCycleGoldTitanKill; + + public override void OnEnter() + { + base.OnEnter(); + missionController = GetComponent(); + bossInvulnerabilityStartTime = Run.FixedTimeStamp.negativeInfinity; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + ServerFixedUpdate(); + } + } + + private void SetBossImmunity(bool newBossImmunity) + { + if (!scriptedCombatEncounter || newBossImmunity == bossImmunity) + { + return; + } + bossImmunity = newBossImmunity; + foreach (CharacterMaster readOnlyMembers in scriptedCombatEncounter.combatSquad.readOnlyMembersList) + { + CharacterBody body = readOnlyMembers.GetBody(); + if ((bool)body) + { + if (bossImmunity) + { + body.AddBuff(RoR2Content.Buffs.Immune); + continue; + } + EffectManager.SpawnEffect(shieldRemovalEffectPrefab, new EffectData + { + origin = body.coreTransform.position + }, transmit: true); + body.RemoveBuff(RoR2Content.Buffs.Immune); + } + } + } + + private void ExtinguishBeacons() + { + foreach (GameObject beaconInstance in missionController.beaconInstanceList) + { + beaconInstance.GetComponent().SetNextState(new NotReady()); + } + } + + private void ServerFixedUpdate() + { + if (base.fixedAge >= transitionDuration) + { + missionController.ExitTransitionIntoBossfight(); + if (!hasSpawnedBoss) + { + SpawnBoss(); + } + else if (scriptedCombatEncounter.combatSquad.readOnlyMembersList.Count == 0) + { + outer.SetNextState(new Exit()); + if (serverCycleCount < 1) + { + GoldshoresBossfight.onOneCycleGoldTitanKill?.Invoke(); + } + return; + } + } + if (!scriptedCombatEncounter) + { + return; + } + if (!bossImmunity) + { + if (bossInvulnerabilityStartTime.hasPassed) + { + ExtinguishBeacons(); + SetBossImmunity(newBossImmunity: true); + serverCycleCount++; + } + } + else if (missionController.beaconsActive >= missionController.beaconsToSpawnOnMap) + { + SetBossImmunity(newBossImmunity: false); + bossInvulnerabilityStartTime = Run.FixedTimeStamp.now + shieldRemovalDuration; + } + } + + private void SpawnBoss() + { + if (!hasSpawnedBoss) + { + if (!scriptedCombatEncounter) + { + scriptedCombatEncounter = UnityEngine.Object.Instantiate(combatEncounterPrefab).GetComponent(); + scriptedCombatEncounter.GetComponent().dropPosition = missionController.bossSpawnPosition; + NetworkServer.Spawn(scriptedCombatEncounter.gameObject); + } + scriptedCombatEncounter.BeginEncounter(); + hasSpawnedBoss = scriptedCombatEncounter.hasSpawnedServer; + if (hasSpawnedBoss) + { + SetBossImmunity(newBossImmunity: true); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.LunarScavengerEncounter/FadeOut.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.LunarScavengerEncounter/FadeOut.cs new file mode 100644 index 0000000..e100978 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.LunarScavengerEncounter/FadeOut.cs @@ -0,0 +1,107 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.Rendering.PostProcessing; + +namespace EntityStates.Missions.LunarScavengerEncounter; + +public class FadeOut : BaseState +{ + public static float delay; + + public static float duration; + + private Run.TimeStamp startTime; + + private Light light; + + private float initialIntensity; + + private float initialAmbientIntensity; + + private Color initialAmbientColor; + + private Color initialFogColor; + + private PostProcessVolume postProcessVolume; + + private bool finished; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + startTime = Run.TimeStamp.now + delay; + } + light = GetComponent().FindChild("PrimaryLight").GetComponent(); + initialIntensity = light.intensity; + initialAmbientIntensity = RenderSettings.ambientIntensity; + initialAmbientColor = RenderSettings.ambientLight; + initialFogColor = RenderSettings.fogColor; + light.GetComponent().enabled = false; + postProcessVolume = GetComponent(); + postProcessVolume.enabled = true; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(startTime); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + startTime = reader.ReadTimeStamp(); + } + + public override void Update() + { + base.Update(); + float num = Mathf.Clamp01(startTime.timeSince / duration); + num *= num; + light.intensity = Mathf.Lerp(initialIntensity, 0f, num); + RenderSettings.ambientIntensity = Mathf.Lerp(initialAmbientIntensity, 0f, num); + RenderSettings.ambientLight = Color.Lerp(initialAmbientColor, Color.black, num); + RenderSettings.fogColor = Color.Lerp(initialFogColor, Color.black, num); + if (!Mathf.Approximately(postProcessVolume.weight, num)) + { + PostProcessVolume.DispatchVolumeSettingsChangedEvent(); + } + postProcessVolume.weight = num; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + FixedUpdateServer(); + } + if (!(startTime.timeSince > duration)) + { + return; + } + foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) + { + if (readOnlyInstances.hasEffectiveAuthority) + { + EntityStateMachine entityStateMachine = EntityStateMachine.FindByCustomName(readOnlyInstances.gameObject, "Body"); + if ((bool)entityStateMachine && !(entityStateMachine.state is Idle)) + { + entityStateMachine.SetInterruptState(new Idle(), InterruptPriority.Frozen); + } + } + } + } + + private void FixedUpdateServer() + { + if ((startTime + duration).hasPassed && !finished) + { + finished = true; + Run.instance.BeginGameOver(RoR2Content.GameEndings.LimboEnding); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.LunarScavengerEncounter/WaitForAllMonstersDead.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.LunarScavengerEncounter/WaitForAllMonstersDead.cs new file mode 100644 index 0000000..8458ab8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.LunarScavengerEncounter/WaitForAllMonstersDead.cs @@ -0,0 +1,24 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.Missions.LunarScavengerEncounter; + +public class WaitForAllMonstersDead : BaseState +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + FixedUpdateServer(); + } + } + + private void FixedUpdateServer() + { + if (TeamComponent.GetTeamMembers(TeamIndex.Monster).Count == 0) + { + outer.SetNextState(new FadeOut()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryActive.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryActive.cs new file mode 100644 index 0000000..636f492 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryActive.cs @@ -0,0 +1,94 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Moon; + +public class MoonBatteryActive : MoonBatteryBaseState +{ + public static string soundEntryEvent; + + public static string soundLoopStartEvent; + + public static string soundLoopEndEvent; + + public static string soundExitEvent; + + public static string activeTriggerName; + + public static string completeTriggerName; + + private HoldoutZoneController holdoutZoneController; + + private ChargeIndicatorController chargeIndicatorController; + + private static int ActivecycleOffsetParamHash = Animator.StringToHash("Active.cycleOffset"); + + public override void OnEnter() + { + base.OnEnter(); + holdoutZoneController = GetComponent(); + holdoutZoneController.enabled = true; + if (NetworkServer.active) + { + GetComponent().enabled = true; + } + Animator[] array = animators; + for (int i = 0; i < array.Length; i++) + { + array[i].SetTrigger(activeTriggerName); + } + Util.PlaySound(soundEntryEvent, base.gameObject); + Util.PlaySound(soundLoopStartEvent, base.gameObject); + FindModelChild("ChargingFX").gameObject.SetActive(value: true); + Transform targetTransform = FindModelChild("PositionIndicatorPosition").transform; + PositionIndicator component = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/PositionIndicators/PillarChargingPositionIndicator"), base.transform.position, Quaternion.identity).GetComponent(); + component.targetTransform = targetTransform; + chargeIndicatorController = component.GetComponent(); + chargeIndicatorController.holdoutZoneController = holdoutZoneController; + } + + public override void Update() + { + base.Update(); + if ((bool)holdoutZoneController) + { + Animator[] array = animators; + for (int i = 0; i < array.Length; i++) + { + array[i].SetFloat(ActivecycleOffsetParamHash, holdoutZoneController.charge * 0.99f); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && holdoutZoneController.charge >= 1f) + { + outer.SetNextState(new MoonBatteryComplete()); + } + } + + public override void OnExit() + { + FindModelChild("ChargingFX").gameObject.SetActive(value: false); + if ((bool)holdoutZoneController) + { + holdoutZoneController.enabled = false; + } + Animator[] array = animators; + for (int i = 0; i < array.Length; i++) + { + array[i].SetTrigger(completeTriggerName); + } + Util.PlaySound(soundLoopEndEvent, base.gameObject); + Util.PlaySound(soundExitEvent, base.gameObject); + if ((bool)chargeIndicatorController) + { + EntityState.Destroy(chargeIndicatorController.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryBaseState.cs new file mode 100644 index 0000000..97bffcb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryBaseState.cs @@ -0,0 +1,18 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Missions.Moon; + +public abstract class MoonBatteryBaseState : BaseState +{ + protected PurchaseInteraction purchaseInteraction; + + protected Animator[] animators; + + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction = GetComponent(); + animators = outer.GetComponentsInChildren(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryBloodActive.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryBloodActive.cs new file mode 100644 index 0000000..f863532 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryBloodActive.cs @@ -0,0 +1,39 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Moon; + +public class MoonBatteryBloodActive : MoonBatteryActive +{ + [SerializeField] + public GameObject siphonPrefab; + + [SerializeField] + public string siphonRootName; + + private GameObject siphonObject; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + Transform transform = FindModelChild(siphonRootName); + if (!transform) + { + transform = base.transform; + } + siphonObject = Object.Instantiate(siphonPrefab, transform.position, transform.rotation, transform); + NetworkServer.Spawn(siphonObject); + } + } + + public override void OnExit() + { + if (NetworkServer.active && (bool)siphonObject) + { + NetworkServer.Destroy(siphonObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryComplete.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryComplete.cs new file mode 100644 index 0000000..ea98e89 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryComplete.cs @@ -0,0 +1,10 @@ +namespace EntityStates.Missions.Moon; + +public class MoonBatteryComplete : MoonBatteryBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + FindModelChild("ChargedFX").gameObject.SetActive(value: true); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryDesignActive.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryDesignActive.cs new file mode 100644 index 0000000..57cc65e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryDesignActive.cs @@ -0,0 +1,113 @@ +using System.Collections.Generic; +using HG; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.Moon; + +public class MoonBatteryDesignActive : MoonBatteryActive +{ + private TeamFilter teamFilter; + + public static GameObject pulsePrefab; + + public static float pulseInterval; + + public static BuffDef buffDef; + + public static float buffDuration; + + public static float baseForce; + + private float pulseTimer; + + public override void OnEnter() + { + base.OnEnter(); + teamFilter = GetComponent(); + pulseTimer = 0f; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + pulseTimer -= GetDeltaTime(); + if (pulseTimer < 0f) + { + pulseTimer = pulseInterval; + CreatePulseServer(); + } + } + } + + private void CreatePulseServer() + { + if (!FindModelChild("PulseOrigin")) + { + _ = base.transform; + } + GameObject obj = Object.Instantiate(pulsePrefab, base.transform.position, base.transform.rotation); + SphereSearch sphereSearch = new SphereSearch(); + PulseController component = obj.GetComponent(); + component.performSearch += PerformPulseSearch; + component.onPulseHit += OnPulseHit; + component.StartPulseServer(); + NetworkServer.Spawn(obj); + static void OnPulseHit(PulseController _, PulseController.PulseHit hitInfo) + { + HealthComponent healthComponent = hitInfo.hitObject as HealthComponent; + if ((bool)healthComponent) + { + CharacterBody body = healthComponent.body; + if ((bool)body.characterMotor && body.characterMotor.isGrounded) + { + Vector3 normalized = (hitInfo.hitPos - hitInfo.pulseOrigin).normalized; + body.characterMotor.ApplyForce(normalized * (baseForce * hitInfo.hitSeverity)); + body.AddTimedBuff(buffDef, buffDuration); + } + } + } + void PerformPulseSearch(PulseController _, Vector3 origin, float radius, List dest) + { + TeamMask none = TeamMask.none; + none.AddTeam(teamFilter.teamIndex); + sphereSearch.origin = origin; + sphereSearch.radius = radius; + sphereSearch.queryTriggerInteraction = QueryTriggerInteraction.Ignore; + sphereSearch.mask = LayerIndex.entityPrecise.mask; + sphereSearch.RefreshCandidates(); + sphereSearch.FilterCandidatesByHurtBoxTeam(none); + sphereSearch.OrderCandidatesByDistance(); + sphereSearch.FilterCandidatesByDistinctHurtBoxEntities(); + List list = CollectionPool>.RentCollection(); + sphereSearch.GetHurtBoxes(list); + for (int i = 0; i < list.Count; i++) + { + HurtBox hurtBox = list[i]; + if ((bool)hurtBox) + { + _ = hurtBox.healthComponent; + if ((bool)hurtBox.healthComponent) + { + Vector3 vector = hurtBox.collider.ClosestPoint(origin); + Vector3.Distance(origin, vector); + PulseController.PulseSearchResult pulseSearchResult = default(PulseController.PulseSearchResult); + pulseSearchResult.hitObject = hurtBox.healthComponent; + pulseSearchResult.hitPos = vector; + PulseController.PulseSearchResult item = pulseSearchResult; + dest.Add(item); + } + } + } + list = CollectionPool>.ReturnCollection(list); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryDisabled.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryDisabled.cs new file mode 100644 index 0000000..66ab337 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryDisabled.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Missions.Moon; + +public class MoonBatteryDisabled : MoonBatteryBaseState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryInactive.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryInactive.cs new file mode 100644 index 0000000..42ce081 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.Moon/MoonBatteryInactive.cs @@ -0,0 +1,18 @@ +namespace EntityStates.Missions.Moon; + +public class MoonBatteryInactive : MoonBatteryBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + purchaseInteraction.SetAvailable(newAvailable: true); + FindModelChild("InactiveFX").gameObject.SetActive(value: true); + } + + public override void OnExit() + { + FindModelChild("InactiveFX").gameObject.SetActive(value: false); + purchaseInteraction.SetAvailable(newAvailable: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.RaidGauntletEncounter/Listening.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.RaidGauntletEncounter/Listening.cs new file mode 100644 index 0000000..f208797 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.RaidGauntletEncounter/Listening.cs @@ -0,0 +1,233 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.RaidGauntletEncounter; + +public class Listening : EntityState +{ + public static float delayBeforeBeginningEncounter; + + public static int shardsDestroyedToTriggerEncounter = 5; + + private GameObject exitPortal; + + private List shardList = new List(); + + private const float delayBeforeRegisteringShards = 2f; + + private bool hasRegisteredShards; + + private int previousDestroyedShardCount; + + private bool beginEncounterCountdown; + + private bool beginGauntletCountdown; + + private bool gauntletTwentySecondWarning; + + private bool gauntletTenSecondWarning; + + private bool gauntletFiveSecondWarning; + + private bool beginGauntletFinalCountdown; + + private const float delayBeforeBeginningGauntletCountdown = 15f; + + private float gauntletFinalCountdown; + + private int secondsRemaining = 4; + + private bool gauntletEnd; + + private bool hasExitPortal; + + private int totalSeconds; + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!NetworkServer.active) + { + return; + } + if (base.fixedAge >= 2f) + { + RegisterShards(); + RegisterExitPortal(); + } + if (base.fixedAge >= 15f && !beginGauntletCountdown) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_START" + }); + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_FIVE_SHARDS_REMAINING" + }); + beginGauntletCountdown = true; + } + if (base.fixedAge >= 25f && !gauntletTwentySecondWarning) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TWENTY_SECONDS_WARNING" + }); + gauntletTwentySecondWarning = true; + } + if (base.fixedAge >= 35f && !gauntletTenSecondWarning) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TEN_SECONDS_WARNING" + }); + gauntletTenSecondWarning = true; + } + if (base.fixedAge >= 40f && !gauntletFiveSecondWarning) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_FIVE_SECONDS_WARNING" + }); + gauntletFiveSecondWarning = true; + beginGauntletFinalCountdown = true; + } + if (!hasRegisteredShards) + { + return; + } + int num = 0; + for (int i = 0; i < shardList.Count; i++) + { + if (shardList[i] == null) + { + num++; + } + } + if (previousDestroyedShardCount != num) + { + switch (shardsDestroyedToTriggerEncounter - num) + { + case 4: + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_FOUR_SHARDS_REMAINING" + }); + break; + case 3: + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_THREE_SHARDS_REMAINING" + }); + break; + case 2: + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TWO_SHARDS_REMAINING" + }); + break; + } + } + int num2 = shardsDestroyedToTriggerEncounter - 1; + if (previousDestroyedShardCount < num2 && num >= num2) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_ONE_SHARD_REMAINING" + }); + } + if (num >= shardsDestroyedToTriggerEncounter && !beginEncounterCountdown) + { + beginEncounterCountdown = true; + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_ALL_SHARDS_DESTROYED" + }); + } + if (beginGauntletFinalCountdown && !gauntletEnd) + { + gauntletFinalCountdown += GetDeltaTime(); + if (gauntletFinalCountdown >= 1f) + { + secondsRemaining--; + totalSeconds++; + if (totalSeconds == 1) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_FOUR_SECONDS_REMAINING" + }); + } + else if (totalSeconds == 2) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_THREE_SECONDS_REMAINING" + }); + } + else if (totalSeconds == 3) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TWO_SECONDS_REMAINING" + }); + } + else if (totalSeconds == 4) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_ONE_SECOND_REMAINING" + }); + } + gauntletFinalCountdown = 0f; + } + if (secondsRemaining == 0) + { + gauntletEnd = true; + exitPortal.SetActive(value: false); + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_END" + }); + } + } + previousDestroyedShardCount = num; + } + + private void RegisterShards() + { + if (hasRegisteredShards) + { + return; + } + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + if (readOnlyInstancesList[i].name.Contains("GauntletShard")) + { + shardList.Add(readOnlyInstancesList[i].gameObject); + } + } + hasRegisteredShards = true; + } + + private void RegisterExitPortal() + { + if (!hasExitPortal) + { + exitPortal = GameObject.Find("PortalArena"); + if ((bool)exitPortal) + { + hasExitPortal = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.RaidGauntletEncounterSlowDeath/Listening.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.RaidGauntletEncounterSlowDeath/Listening.cs new file mode 100644 index 0000000..e84ec10 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.RaidGauntletEncounterSlowDeath/Listening.cs @@ -0,0 +1,230 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.RaidGauntletEncounterSlowDeath; + +public class Listening : EntityState +{ + public static float delayBeforeBeginningEncounter; + + public static int shardsDestroyedToTriggerEncounter; + + private List shardList = new List(); + + private const float delayBeforeRegisteringShards = 2f; + + private bool hasRegisteredShards; + + private int previousDestroyedShardCount; + + private bool beginEncounterCountdown; + + private bool beginGauntletCountdown; + + private bool gauntletTwentySecondWarning; + + private bool gauntletTenSecondWarning; + + private bool gauntletFiveSecondWarning; + + private bool beginGauntletFinalCountdown; + + private const float delayBeforeBeginningGauntletCountdown = 15f; + + private float gauntletFinalCountdown; + + private int secondsRemaining = 4; + + private bool gauntletEnd; + + private int totalSeconds; + + private GameObject slowDeathEffect; + + private bool slowDeathEffectActive; + + private GauntletMissionController gauntletMissionController; + + private GameObject gMC; + + private float degenTickFrequency; + + private float percentDegenPerSecond; + + private bool hasGauntletMissionController; + + private bool theEnd; + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!NetworkServer.active) + { + return; + } + if (base.fixedAge >= 2f) + { + RegisterShards(); + RegisterGauntletMissionController(); + } + if (base.fixedAge >= 15f && !beginGauntletCountdown) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_START" + }); + beginGauntletCountdown = true; + } + if (base.fixedAge >= 25f && !gauntletTwentySecondWarning) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TWENTY_SECONDS_WARNING" + }); + gauntletTwentySecondWarning = true; + } + if (base.fixedAge >= 35f && !gauntletTenSecondWarning) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TEN_SECONDS_WARNING" + }); + gauntletTenSecondWarning = true; + } + if (base.fixedAge >= 40f && !gauntletFiveSecondWarning) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_FIVE_SECONDS_WARNING" + }); + gauntletFiveSecondWarning = true; + beginGauntletFinalCountdown = true; + } + if (!hasRegisteredShards) + { + return; + } + int num = 0; + for (int i = 0; i < shardList.Count; i++) + { + if (shardList[i] == null) + { + num++; + } + } + if (previousDestroyedShardCount != num) + { + _ = shardsDestroyedToTriggerEncounter; + } + int num2 = shardsDestroyedToTriggerEncounter - 1; + if (previousDestroyedShardCount < num2 && num >= num2) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_ONE_SHARD_REMAINING" + }); + } + if (num >= shardsDestroyedToTriggerEncounter && !beginEncounterCountdown) + { + beginEncounterCountdown = true; + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_ALL_SHARDS_DESTROYED" + }); + } + if (beginGauntletFinalCountdown && !gauntletEnd) + { + gauntletFinalCountdown += GetDeltaTime(); + if (gauntletFinalCountdown >= 1f) + { + secondsRemaining--; + totalSeconds++; + if (totalSeconds == 1) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_FOUR_SECONDS_REMAINING" + }); + } + else if (totalSeconds == 2) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_THREE_SECONDS_REMAINING" + }); + } + else if (totalSeconds == 3) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_TWO_SECONDS_REMAINING" + }); + } + else if (totalSeconds == 4) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_ONE_SECOND_REMAINING" + }); + } + gauntletFinalCountdown = 0f; + } + if (secondsRemaining == 0) + { + gauntletEnd = true; + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "GAUNTLET_SLOWDEATH_END" + }); + } + } + if (gauntletEnd && !theEnd) + { + gauntletMissionController.GauntletMissionTimesUp(); + theEnd = true; + } + previousDestroyedShardCount = num; + } + + private void RegisterShards() + { + if (hasRegisteredShards) + { + return; + } + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + if (readOnlyInstancesList[i].name.Contains("GauntletShard")) + { + shardList.Add(readOnlyInstancesList[i].gameObject); + } + } + shardsDestroyedToTriggerEncounter = shardList.Count; + hasRegisteredShards = true; + } + + private void RegisterGauntletMissionController() + { + if (!hasGauntletMissionController) + { + gMC = GameObject.Find("GauntletMissionController"); + gauntletMissionController = gMC.GetComponent(); + if ((bool)gauntletMissionController) + { + slowDeathEffect = gauntletMissionController.clearedEffect; + degenTickFrequency = gauntletMissionController.degenTickFrequency; + percentDegenPerSecond = gauntletMissionController.percentDegenPerSecond; + hasGauntletMissionController = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Missions.SuperRoboBallEncounter/Listening.cs b/ilspy_dump/ror2_csproj/EntityStates.Missions.SuperRoboBallEncounter/Listening.cs new file mode 100644 index 0000000..5eae6f5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Missions.SuperRoboBallEncounter/Listening.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Missions.SuperRoboBallEncounter; + +public class Listening : EntityState +{ + public static float delayBeforeBeginningEncounter; + + public static int eggsDestroyedToTriggerEncounter; + + private ScriptedCombatEncounter scriptedCombatEncounter; + + private List eggList = new List(); + + private const float delayBeforeRegisteringEggs = 2f; + + private bool hasRegisteredEggs; + + private int previousDestroyedEggCount; + + private bool beginEncounterCountdown; + + private float encounterCountdown; + + public override void OnEnter() + { + base.OnEnter(); + scriptedCombatEncounter = GetComponent(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!NetworkServer.active) + { + return; + } + if (base.fixedAge >= 2f) + { + RegisterEggs(); + } + if (!hasRegisteredEggs) + { + return; + } + int num = 0; + for (int i = 0; i < eggList.Count; i++) + { + if (eggList[i] == null) + { + num++; + } + } + int num2 = eggsDestroyedToTriggerEncounter - 1; + if (previousDestroyedEggCount < num2 && num >= num2) + { + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "VULTURE_EGG_WARNING" + }); + } + if (num >= eggsDestroyedToTriggerEncounter && !beginEncounterCountdown) + { + encounterCountdown = delayBeforeBeginningEncounter; + beginEncounterCountdown = true; + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = "VULTURE_EGG_BEGIN" + }); + } + if (beginEncounterCountdown) + { + encounterCountdown -= GetDeltaTime(); + if (encounterCountdown <= 0f) + { + scriptedCombatEncounter.BeginEncounter(); + outer.SetNextState(new Idle()); + } + } + previousDestroyedEggCount = num; + } + + private void RegisterEggs() + { + if (hasRegisteredEggs) + { + return; + } + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + if (readOnlyInstancesList[i].name.Contains("VultureEgg")) + { + eggList.Add(readOnlyInstancesList[i].gameObject); + } + } + hasRegisteredEggs = true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/Inactive.cs b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/Inactive.cs new file mode 100644 index 0000000..6bca058 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/Inactive.cs @@ -0,0 +1,21 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MoonElevator; + +public class Inactive : MoonElevatorBaseState +{ + private static int InactiveStateHash = Animator.StringToHash("Inactive"); + + public override Interactability interactability => Interactability.ConditionsNotMet; + + public override bool goToNextStateAutomatically => false; + + public override bool showBaseEffects => false; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", InactiveStateHash); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/InactiveToReady.cs b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/InactiveToReady.cs new file mode 100644 index 0000000..935c615 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/InactiveToReady.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MoonElevator; + +public class InactiveToReady : MoonElevatorBaseState +{ + private static int InactiveToActiveStateHash = Animator.StringToHash("InactiveToActive"); + + private static int playbackRateParamHash = Animator.StringToHash("playbackRate"); + + public override Interactability interactability => Interactability.Disabled; + + public override bool goToNextStateAutomatically => true; + + public override EntityState nextState => new Ready(); + + public override bool showBaseEffects => true; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", InactiveToActiveStateHash, playbackRateParamHash, duration); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/MoonElevatorBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/MoonElevatorBaseState.cs new file mode 100644 index 0000000..cb06cee --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/MoonElevatorBaseState.cs @@ -0,0 +1,53 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.MoonElevator; + +public abstract class MoonElevatorBaseState : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string enterSfxString; + + protected GenericInteraction genericInteraction; + + public virtual EntityState nextState => new Uninitialized(); + + public virtual Interactability interactability => Interactability.Disabled; + + public virtual bool goToNextStateAutomatically => false; + + public virtual bool showBaseEffects => false; + + public override void OnEnter() + { + base.OnEnter(); + genericInteraction = GetComponent(); + Util.PlaySound(enterSfxString, base.gameObject); + if (NetworkServer.active) + { + genericInteraction.Networkinteractability = interactability; + if (interactability == Interactability.Available) + { + genericInteraction.onActivation?.AddListener(OnInteractionBegin); + } + } + FindModelChild("EffectBase").gameObject.SetActive(showBaseEffects); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration && base.isAuthority && goToNextStateAutomatically) + { + outer.SetNextState(nextState); + } + } + + protected virtual void OnInteractionBegin(Interactor activator) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/Ready.cs b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/Ready.cs new file mode 100644 index 0000000..f4f7ace --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.MoonElevator/Ready.cs @@ -0,0 +1,27 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.MoonElevator; + +public class Ready : MoonElevatorBaseState +{ + private static int ReadyStateHash = Animator.StringToHash("Ready"); + + public override Interactability interactability => Interactability.Available; + + public override bool goToNextStateAutomatically => false; + + public override bool showBaseEffects => true; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", ReadyStateHash); + } + + protected override void OnInteractionBegin(Interactor activator) + { + base.OnInteractionBegin(activator); + _ = base.isAuthority; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.NewtMonster/KickFromShop.cs b/ilspy_dump/ror2_csproj/EntityStates.NewtMonster/KickFromShop.cs new file mode 100644 index 0000000..c49cb5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.NewtMonster/KickFromShop.cs @@ -0,0 +1,127 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.NewtMonster; + +public class KickFromShop : BaseState +{ + public static float duration = 3.5f; + + public static string attackSoundString; + + public static string stompSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject stompEffectPrefab; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + private GameObject chargeEffectInstance; + + private EffectManagerHelper _emh_chargeEffectInstance; + + public override void Reset() + { + base.Reset(); + modelAnimator = null; + modelTransform = null; + hasAttacked = false; + chargeEffectInstance = null; + _emh_chargeEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("Body", "Stomp", "Stomp.playbackRate", duration, 0.1f); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("StompMuzzle"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform); + return; + } + _emh_chargeEffectInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform, inResetLocal: true); + chargeEffectInstance = _emh_chargeEffectInstance.gameObject; + } + } + + protected void DestroyChargeEffect() + { + if (chargeEffectInstance != null) + { + if (_emh_chargeEffectInstance != null && _emh_chargeEffectInstance.OwningPool != null) + { + _emh_chargeEffectInstance.OwningPool.ReturnObject(_emh_chargeEffectInstance); + } + else + { + EntityState.Destroy(chargeEffectInstance); + } + chargeEffectInstance = null; + _emh_chargeEffectInstance = null; + } + } + + public override void OnExit() + { + DestroyChargeEffect(); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("Stomp.hitBoxActive") > 0.5f && !hasAttacked) + { + Util.PlayAttackSpeedSound(stompSoundString, base.gameObject, attackSpeedStat); + EffectManager.SimpleMuzzleFlash(stompEffectPrefab, base.gameObject, "HealthBarOrigin", transmit: false); + if ((bool)SceneInfo.instance) + { + GameObject gameObject = SceneInfo.instance.transform.Find("KickOutOfShop").gameObject; + if ((bool)gameObject) + { + gameObject.gameObject.SetActive(value: true); + } + } + if (base.isAuthority) + { + HurtBoxGroup component = modelTransform.GetComponent(); + if ((bool)component) + { + int hurtBoxesDeactivatorCounter = component.hurtBoxesDeactivatorCounter + 1; + component.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + } + hasAttacked = true; + DestroyChargeEffect(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.NewtMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.NewtMonster/SpawnState.cs new file mode 100644 index 0000000..a696885 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.NewtMonster/SpawnState.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.NewtMonster; + +public class SpawnState : EntityState +{ + public static float duration = 2f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + GetModelAnimator(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "SpawnEffectOrigin", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/AimPortalBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/AimPortalBomb.cs new file mode 100644 index 0000000..2c46a55 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/AimPortalBomb.cs @@ -0,0 +1,93 @@ +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.NullifierMonster; + +public class AimPortalBomb : BaseState +{ + private HurtBox target; + + public static float baseDuration; + + public static float arcMultiplier; + + private float duration; + + private Vector3? pointA; + + private Vector3? pointB; + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.searchOrigin = base.characterBody.corePosition; + bullseyeSearch.searchDirection = base.characterBody.corePosition; + bullseyeSearch.maxDistanceFilter = FirePortalBomb.maxDistance; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.RefreshCandidates(); + target = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)target) + { + pointA = RaycastToFloor(target.transform.position); + } + } + duration = baseDuration; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority || !(base.fixedAge >= duration)) + { + return; + } + EntityState entityState = null; + if ((bool)target) + { + pointB = RaycastToFloor(target.transform.position); + if (pointA.HasValue && pointB.HasValue) + { + Ray aimRay = GetAimRay(); + Vector3 forward = pointA.Value - aimRay.origin; + Vector3 forward2 = pointB.Value - aimRay.origin; + Quaternion a = Quaternion.LookRotation(forward); + Quaternion quaternion = Quaternion.LookRotation(forward2); + Quaternion value = quaternion; + Quaternion value2 = Quaternion.SlerpUnclamped(a, quaternion, 1f + arcMultiplier); + entityState = new FirePortalBomb + { + startRotation = value, + endRotation = value2 + }; + } + } + if (entityState != null) + { + outer.SetNextState(entityState); + } + else + { + outer.SetNextStateToMain(); + } + } + + private Vector3? RaycastToFloor(Vector3 position) + { + if (Physics.Raycast(new Ray(position, Vector3.down), out var hitInfo, 10f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + return hitInfo.point; + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/DeathState.cs new file mode 100644 index 0000000..ea09f19 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/DeathState.cs @@ -0,0 +1,59 @@ +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.NullifierMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathBombProjectile; + + public static float duration; + + public static string muzzleName; + + private Transform muzzleTransform; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayCrossfade("Body", "Death", "Death.playbackRate", duration, 0.1f); + } + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + if ((bool)muzzleTransform && base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = deathBombProjectile; + fireProjectileInfo.position = muzzleTransform.position; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat; + fireProjectileInfo.crit = base.characterBody.RollCrit(); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/FirePortalBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/FirePortalBomb.cs new file mode 100644 index 0000000..4067c8c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/FirePortalBomb.cs @@ -0,0 +1,113 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.NullifierMonster; + +public class FirePortalBomb : BaseState +{ + public static GameObject portalBombProjectileEffect; + + public static GameObject muzzleflashEffectPrefab; + + public static string muzzleString; + + public static int portalBombCount; + + public static float baseDuration; + + public static float maxDistance; + + public static float damageCoefficient; + + public static float procCoefficient; + + public static float randomRadius; + + public static float force; + + public static float minimumDistanceBetweenBombs; + + public Quaternion? startRotation; + + public Quaternion? endRotation; + + private float duration; + + private int bombsFired; + + private float fireTimer; + + private float fireInterval; + + private Vector3 lastBombPosition; + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + StartAimMode(4f); + if (base.isAuthority) + { + fireInterval = duration / (float)portalBombCount; + fireTimer = 0f; + } + } + + private void FireBomb(Ray fireRay) + { + if (Physics.Raycast(fireRay, out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + Vector3 point = hitInfo.point; + Vector3 vector = point - lastBombPosition; + if (bombsFired > 0 && vector.sqrMagnitude < minimumDistanceBetweenBombs * minimumDistanceBetweenBombs) + { + point += vector.normalized * minimumDistanceBetweenBombs; + } + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = portalBombProjectileEffect; + fireProjectileInfo.position = point; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = base.characterBody.RollCrit(); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + lastBombPosition = point; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + fireTimer += fireInterval; + if (startRotation.HasValue && endRotation.HasValue) + { + float num = 1f / ((float)portalBombCount - 1f); + float t = (float)bombsFired * num; + Ray aimRay = GetAimRay(); + Quaternion quaternion = Quaternion.Slerp(startRotation.Value, endRotation.Value, t); + aimRay.direction = quaternion * Vector3.forward; + FireBomb(aimRay); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: true); + } + bombsFired++; + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/SpawnState.cs new file mode 100644 index 0000000..b2bf187 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.NullifierMonster/SpawnState.cs @@ -0,0 +1,47 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.NullifierMonster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "PortalEffect", transmit: false); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + modelTransform.GetComponent().enabled = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/BarrierUp.cs b/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/BarrierUp.cs new file mode 100644 index 0000000..9badd6d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/BarrierUp.cs @@ -0,0 +1,50 @@ +using RoR2; + +namespace EntityStates.Paladin.PaladinWeapon; + +public class BarrierUp : BaseState +{ + public static float duration = 5f; + + public static string soundEffectString; + + private float stopwatch; + + private PaladinBarrierController paladinBarrierController; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundEffectString, base.gameObject); + stopwatch = 0f; + paladinBarrierController = GetComponent(); + if ((bool)paladinBarrierController) + { + paladinBarrierController.EnableBarrier(); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)paladinBarrierController) + { + paladinBarrierController.DisableBarrier(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= 0.1f && !base.inputBank.skill2.down && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/FireBigRocket.cs b/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/FireBigRocket.cs new file mode 100644 index 0000000..d6fdf0e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/FireBigRocket.cs @@ -0,0 +1,60 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Paladin.PaladinWeapon; + +public class FireBigRocket : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static string soundEffectString; + + public static float damageCoefficient; + + public static float force; + + public static float baseDuration = 2f; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundEffectString, base.gameObject); + duration = baseDuration / attackSpeedStat; + base.characterBody.AddSpreadBloom(1f); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "MuzzleCenter"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/FireRocket.cs b/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/FireRocket.cs new file mode 100644 index 0000000..cf75105 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Paladin.PaladinWeapon/FireRocket.cs @@ -0,0 +1,62 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Paladin.PaladinWeapon; + +public class FireRocket : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + public static string soundEffectString; + + public static float damageCoefficient; + + public static float force; + + public static float baseDuration = 2f; + + private float duration; + + public int bulletCountCurrent = 1; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(soundEffectString, base.gameObject); + duration = baseDuration / attackSpeedStat; + base.characterBody.AddSpreadBloom(0.3f); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + string muzzleName = "MuzzleCenter"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Paladin/DashSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.Paladin/DashSlam.cs new file mode 100644 index 0000000..b7d4eac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Paladin/DashSlam.cs @@ -0,0 +1,172 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Paladin; + +public class DashSlam : BaseState +{ + private float stopwatch; + + public static float damageCoefficient = 4f; + + public static float baseForceMagnitude = 16f; + + public static float bonusImpactForce; + + public static string initialAttackSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject slamEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static float initialSpeedCoefficient; + + public static float finalSpeedCoefficient; + + public static float duration; + + public static float overlapSphereRadius; + + public static float blastAttackRadius; + + private BlastAttack attack; + + private Transform modelTransform; + + private GameObject leftHandChargeEffect; + + private GameObject rightHandChargeEffect; + + private ChildLocator modelChildLocator; + + private Vector3 initialAimVector; + + private void EnableIndicator(string childLocatorName, ChildLocator childLocator = null) + { + if (!childLocator) + { + childLocator = GetModelTransform().GetComponent(); + } + Transform transform = childLocator.FindChild(childLocatorName); + if ((bool)transform) + { + transform.gameObject.SetActive(value: true); + ObjectScaleCurve component = transform.gameObject.GetComponent(); + if ((bool)component) + { + component.time = 0f; + } + } + } + + private void DisableIndicator(string childLocatorName, ChildLocator childLocator = null) + { + if (!childLocator) + { + childLocator = GetModelTransform().GetComponent(); + } + Transform transform = childLocator.FindChild(childLocatorName); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + } + + public override void OnEnter() + { + base.OnEnter(); + modelTransform = GetModelTransform(); + Util.PlaySound(initialAttackSoundString, base.gameObject); + initialAimVector = Vector3.ProjectOnPlane(GetAimRay().direction, Vector3.up); + base.characterMotor.velocity.y = 0f; + base.characterDirection.forward = initialAimVector; + attack = new BlastAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.baseDamage = damageCoefficient * damageStat; + attack.damageType = DamageType.Stun1s; + attack.baseForce = baseForceMagnitude; + attack.radius = blastAttackRadius + base.characterBody.radius; + attack.falloffModel = BlastAttack.FalloffModel.None; + attack.attackerFiltering = AttackerFiltering.NeverHitSelf; + if (!modelTransform) + { + return; + } + modelChildLocator = modelTransform.GetComponent(); + if ((bool)modelChildLocator) + { + GameObject original = chargeEffectPrefab; + Transform transform = modelChildLocator.FindChild("HandL"); + Transform transform2 = modelChildLocator.FindChild("HandR"); + if ((bool)transform) + { + leftHandChargeEffect = Object.Instantiate(original, transform); + } + if ((bool)transform2) + { + rightHandChargeEffect = Object.Instantiate(original, transform2); + } + EnableIndicator("GroundSlamIndicator", modelChildLocator); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + attack.position = base.transform.position; + attack.bonusForce = (initialAimVector + Vector3.up * 0.3f) * bonusImpactForce; + attack.Fire(); + } + if (base.isAuthority && (bool)modelTransform) + { + EffectManager.SimpleMuzzleFlash(slamEffectPrefab, base.gameObject, "SlamZone", transmit: true); + } + EntityState.Destroy(leftHandChargeEffect); + EntityState.Destroy(rightHandChargeEffect); + DisableIndicator("GroundSlamIndicator", modelChildLocator); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (base.isAuthority) + { + Collider[] colliders; + int num = HGPhysics.OverlapSphere(out colliders, base.transform.position, base.characterBody.radius + overlapSphereRadius, LayerIndex.entityPrecise.mask); + for (int i = 0; i < num; i++) + { + HurtBox component = colliders[i].GetComponent(); + if ((bool)component && component.healthComponent != base.healthComponent) + { + HGPhysics.ReturnResults(colliders); + outer.SetNextStateToMain(); + return; + } + } + } + if ((bool)base.characterMotor) + { + float num2 = Mathf.Lerp(initialSpeedCoefficient, finalSpeedCoefficient, stopwatch / duration) * base.characterBody.moveSpeed; + Vector3 velocity = new Vector3(initialAimVector.x * num2, 0f, initialAimVector.z * num2); + base.characterMotor.velocity = velocity; + base.characterMotor.moveDirection = initialAimVector; + } + if (stopwatch > duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Paladin/LeapSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.Paladin/LeapSlam.cs new file mode 100644 index 0000000..feab69f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Paladin/LeapSlam.cs @@ -0,0 +1,159 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Paladin; + +public class LeapSlam : BaseState +{ + private float stopwatch; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float yBias; + + public static string initialAttackSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject slamEffectPrefab; + + public static GameObject hitEffectPrefab; + + public static float leapVelocityCoefficient; + + public static float verticalLeapBonusCoefficient; + + public static float minimumDuration; + + private float leapVelocity; + + private OverlapAttack attack; + + private Transform modelTransform; + + private GameObject leftHandChargeEffect; + + private GameObject rightHandChargeEffect; + + private ChildLocator modelChildLocator; + + private Vector3 initialAimVector; + + private void EnableIndicator(string childLocatorName, ChildLocator childLocator = null) + { + if (!childLocator) + { + childLocator = GetModelTransform().GetComponent(); + } + Transform transform = childLocator.FindChild(childLocatorName); + if ((bool)transform) + { + transform.gameObject.SetActive(value: true); + ObjectScaleCurve component = transform.gameObject.GetComponent(); + if ((bool)component) + { + component.time = 0f; + } + } + } + + private void DisableIndicator(string childLocatorName, ChildLocator childLocator = null) + { + if (!childLocator) + { + childLocator = GetModelTransform().GetComponent(); + } + Transform transform = childLocator.FindChild(childLocatorName); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + } + + public override void OnEnter() + { + base.OnEnter(); + leapVelocity = base.characterBody.moveSpeed * leapVelocityCoefficient; + modelTransform = GetModelTransform(); + Util.PlaySound(initialAttackSoundString, base.gameObject); + initialAimVector = GetAimRay().direction; + initialAimVector.y = Mathf.Max(initialAimVector.y, 0f); + initialAimVector.y += yBias; + initialAimVector = initialAimVector.normalized; + base.characterMotor.velocity.y = leapVelocity * initialAimVector.y * verticalLeapBonusCoefficient; + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficient * damageStat; + attack.hitEffectPrefab = hitEffectPrefab; + attack.damageType = DamageType.Stun1s; + attack.forceVector = Vector3.up * forceMagnitude; + if ((bool)modelTransform) + { + attack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "GroundSlam"); + } + if (!modelTransform) + { + return; + } + modelChildLocator = modelTransform.GetComponent(); + if ((bool)modelChildLocator) + { + GameObject original = chargeEffectPrefab; + Transform transform = modelChildLocator.FindChild("HandL"); + Transform transform2 = modelChildLocator.FindChild("HandR"); + if ((bool)transform) + { + leftHandChargeEffect = UnityEngine.Object.Instantiate(original, transform); + } + if ((bool)transform2) + { + rightHandChargeEffect = UnityEngine.Object.Instantiate(original, transform2); + } + EnableIndicator("GroundSlamIndicator", modelChildLocator); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + attack.Fire(); + } + if (base.isAuthority && (bool)modelTransform) + { + EffectManager.SimpleMuzzleFlash(slamEffectPrefab, base.gameObject, "SlamZone", transmit: true); + } + EntityState.Destroy(leftHandChargeEffect); + EntityState.Destroy(rightHandChargeEffect); + DisableIndicator("GroundSlamIndicator", modelChildLocator); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if ((bool)base.characterMotor) + { + Vector3 velocity = base.characterMotor.velocity; + Vector3 velocity2 = new Vector3(initialAimVector.x * leapVelocity, velocity.y, initialAimVector.z * leapVelocity); + base.characterMotor.velocity = velocity2; + base.characterMotor.moveDirection = initialAimVector; + } + if (base.characterMotor.isGrounded && stopwatch > minimumDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/BaseEggState.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/BaseEggState.cs new file mode 100644 index 0000000..8c955cc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/BaseEggState.cs @@ -0,0 +1,14 @@ +using RoR2; + +namespace EntityStates.ParentEgg; + +public class BaseEggState : BaseState +{ + protected SpawnerPodsController controller { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + controller = GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/Death.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/Death.cs new file mode 100644 index 0000000..021457f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/Death.cs @@ -0,0 +1,14 @@ +using RoR2; + +namespace EntityStates.ParentEgg; + +public class Death : GenericCharacterDeath +{ + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + GetComponent().Dissolve(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/Hatch.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/Hatch.cs new file mode 100644 index 0000000..d0f7ca7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/Hatch.cs @@ -0,0 +1,69 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ParentEgg; + +public class Hatch : GenericCharacterDeath +{ + private SpawnerPodsController controller; + + private static int HatchStateHash = Animator.StringToHash("Hatch"); + + public override void OnEnter() + { + controller = GetComponent(); + base.OnEnter(); + if (NetworkServer.active) + { + DoHatch(); + } + } + + protected override void PlayDeathAnimation(float crossfadeDuration) + { + PlayAnimation("Body", HatchStateHash); + EffectManager.SimpleEffect(controller.hatchEffect, base.gameObject.transform.position, base.transform.rotation, transmit: false); + } + + protected override void PlayDeathSound() + { + Util.PlaySound(controller.podHatchSound, base.gameObject); + } + + private void DoHatch() + { + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscParent"), new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Direct, + minDistance = 0f, + maxDistance = 1f, + spawnOnTarget = base.transform + }, RoR2Application.rng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, new Action(OnHatchlingSpawned)); + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + } + + private void OnHatchlingSpawned(SpawnCard.SpawnResult spawnResult) + { + CharacterMaster component = spawnResult.spawnedInstance.GetComponent(); + component.teamIndex = base.characterBody.teamComponent.teamIndex; + CharacterMaster master = base.characterBody.master; + CharacterMaster characterMaster = (master ? master.minionOwnership.ownerMaster : null); + if ((bool)component) + { + Inventory inventory = base.characterBody.master.inventory; + Inventory inventory2 = component.inventory; + inventory2.CopyItemsFrom(inventory); + inventory2.CopyEquipmentFrom(inventory); + GameObject bodyObject = component.GetBodyObject(); + if ((bool)bodyObject && (bool)characterMaster) + { + Deployable component2 = bodyObject.GetComponent(); + characterMaster.AddDeployable(component2, DeployableSlot.ParentAlly); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/IncubateState.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/IncubateState.cs new file mode 100644 index 0000000..12de029 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/IncubateState.cs @@ -0,0 +1,29 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ParentEgg; + +public class IncubateState : BaseEggState +{ + private float duration; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + public override void OnEnter() + { + base.OnEnter(); + duration = base.controller.incubationDuration; + PlayAnimation("Body", SpawnStateHash); + Util.PlaySound(base.controller.podSpawnSound, base.gameObject); + EffectManager.SimpleEffect(base.controller.spawnEffect, base.gameObject.transform.position, base.transform.rotation, transmit: true); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new PreHatch()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/PreHatch.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/PreHatch.cs new file mode 100644 index 0000000..733465d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentEgg/PreHatch.cs @@ -0,0 +1,17 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.ParentEgg; + +public class PreHatch : BaseEggState +{ + public override void OnEnter() + { + base.OnEnter(); + GetComponent().deathState = new SerializableEntityStateType(typeof(Hatch)); + if (NetworkServer.active) + { + base.healthComponent.Suicide(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/DeathState.cs new file mode 100644 index 0000000..954eb1d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/DeathState.cs @@ -0,0 +1,99 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ParentMonster; + +public class DeathState : GenericCharacterDeath +{ + [SerializeField] + public float timeBeforeDestealth = 2.5f; + + [SerializeField] + public float destealthDuration; + + [SerializeField] + public Material destealthMaterial; + + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public string effectMuzzleString; + + private bool destealth; + + protected override bool shouldAutoDestroy + { + get + { + if (destealth) + { + return base.fixedAge > timeBeforeDestealth + destealthDuration; + } + return false; + } + } + + public override void OnEnter() + { + base.OnEnter(); + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > timeBeforeDestealth && !destealth) + { + DoDestealth(); + } + if (destealth && base.fixedAge > timeBeforeDestealth + destealthDuration) + { + DestroyModel(); + } + } + + private void DoDestealth() + { + destealth = true; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, effectMuzzleString, transmit: false); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + CharacterModel component = modelTransform.gameObject.GetComponent(); + if ((bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = destealthDuration; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = component; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + PrintController component2 = base.modelLocator.modelTransform.gameObject.GetComponent(); + component2.enabled = false; + component2.printTime = destealthDuration; + component2.startingPrintHeight = 0f; + component2.maxPrintHeight = 20f; + component2.startingPrintBias = 0f; + component2.maxPrintBias = 2f; + component2.disableWhenFinished = false; + component2.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + component2.enabled = true; + } + Transform transform = FindModelChild("CoreLight"); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/GroundSlam.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/GroundSlam.cs new file mode 100644 index 0000000..299f5a7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/GroundSlam.cs @@ -0,0 +1,90 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ParentMonster; + +public class GroundSlam : BaseState +{ + public static float duration = 3.5f; + + public static float damageCoefficient = 4f; + + public static float forceMagnitude = 16f; + + public static float radius = 3f; + + private BlastAttack attack; + + public static string attackSoundString; + + public static GameObject slamImpactEffect; + + public static GameObject meleeTrailEffectL; + + public static GameObject meleeTrailEffectR; + + private Animator modelAnimator; + + private Transform modelTransform; + + private bool hasAttacked; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSpeedStat); + PlayCrossfade("Body", "Slam", "Slam.playbackRate", duration, 0.1f); + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = GetAimRay().direction; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)modelAnimator && modelAnimator.GetFloat("Slam.hitBoxActive") > 0.5f && !hasAttacked) + { + if (base.isAuthority) + { + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)modelTransform) + { + Transform transform = FindModelChild("SlamZone"); + if ((bool)transform) + { + attack = new BlastAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + attack.baseDamage = damageStat * damageCoefficient; + attack.baseForce = forceMagnitude; + attack.position = transform.position; + attack.radius = radius; + attack.Fire(); + } + } + } + hasAttacked = true; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/LoomingPresence.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/LoomingPresence.cs new file mode 100644 index 0000000..f53232a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/LoomingPresence.cs @@ -0,0 +1,143 @@ +using RoR2; +using RoR2.Navigation; +using UnityEngine; + +namespace EntityStates.ParentMonster; + +public class LoomingPresence : BaseState +{ + private Transform modelTransform; + + public static GameObject blinkPrefab; + + public static Material destealthMaterial; + + private float stopwatch; + + private Vector3 blinkDestination = Vector3.zero; + + private Vector3 blinkStart = Vector3.zero; + + public static float duration = 0.3f; + + public static float blinkDistance = 25f; + + public static string beginSoundString; + + public static string endSoundString; + + public static float destealthDuration; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(beginSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + if (base.isAuthority) + { + Vector3 vector = base.inputBank.aimDirection * blinkDistance; + blinkDestination = base.transform.position; + blinkStart = base.transform.position; + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNode(base.transform.position + vector, base.characterBody.hullClassification); + groundNodes.GetNodePosition(nodeIndex, out blinkDestination); + blinkDestination += base.transform.position - base.characterBody.footPosition; + vector = blinkDestination - blinkStart; + CreateBlinkEffect(Util.GetCorePosition(base.gameObject), vector); + } + } + + private void CreateBlinkEffect(Vector3 origin, Vector3 direction) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(direction); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkPrefab, effectData, transmit: true); + } + + private void SetPosition(Vector3 newPosition) + { + if ((bool)base.characterMotor) + { + base.characterMotor.Motor.SetPositionAndRotation(newPosition, Quaternion.identity); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + base.characterMotor.velocity = Vector3.zero; + } + SetPosition(Vector3.Lerp(blinkStart, blinkDestination, stopwatch / duration)); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + Util.PlaySound(endSoundString, base.gameObject); + modelTransform = GetModelTransform(); + if ((bool)base.characterDirection) + { + base.characterDirection.forward = GetAimRay().direction; + } + if ((bool)modelTransform && (bool)destealthMaterial) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = destealthDuration; + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = destealthMaterial; + temporaryOverlayInstance.inspectorCharacterModel = modelTransform.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.animateShaderAlpha = true; + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = true; + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/SpawnState.cs new file mode 100644 index 0000000..096fa4d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentMonster/SpawnState.cs @@ -0,0 +1,59 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ParentMonster; + +public class SpawnState : EntityState +{ + public static float duration = 2f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private ParentEnergyFXController FXController; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + GetModelAnimator(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + if ((bool)spawnEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = base.modelLocator.modelTransform.GetComponent().FindChild("SpawnEffectOrigin").position + }; + EffectManager.SpawnEffect(spawnEffectPrefab, effectData, transmit: true); + } + PrintController component = base.modelLocator.modelTransform.gameObject.GetComponent(); + component.enabled = false; + component.printTime = duration; + component.startingPrintHeight = 4f; + component.maxPrintHeight = -1f; + component.startingPrintBias = 2f; + component.maxPrintBias = 0.95f; + component.disableWhenFinished = true; + component.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + component.enabled = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ParentPod/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.ParentPod/DeathState.cs new file mode 100644 index 0000000..36c75ed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ParentPod/DeathState.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ParentPod; + +public class DeathState : GenericCharacterDeath +{ + public static float deathAnimTimer; + + private float mDeathAnimTimer; + + public static GameObject deathEffect; + + private bool printingStarted; + + public override void OnEnter() + { + base.OnEnter(); + mDeathAnimTimer = deathAnimTimer; + EffectManager.SimpleEffect(deathEffect, base.gameObject.transform.position, base.transform.rotation, transmit: false); + } + + public override void FixedUpdate() + { + mDeathAnimTimer -= Time.deltaTime; + if (mDeathAnimTimer <= 0f && !printingStarted) + { + printingStarted = true; + PrintController printController = GetComponent().modelTransform.gameObject.AddComponent(); + printController.enabled = false; + printController.printTime = 1f; + printController.startingPrintHeight = 99999f; + printController.maxPrintHeight = 99999f; + printController.startingPrintBias = 0.95f; + printController.maxPrintBias = 1.95f; + printController.animateFlowmapPower = true; + printController.startingFlowmapPower = 1.14f; + printController.maxFlowmapPower = 30f; + printController.disableWhenFinished = false; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + printController.enabled = true; + } + if (printingStarted) + { + base.FixedUpdate(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Pot.PotWeapon/FireCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.Pot.PotWeapon/FireCannon.cs new file mode 100644 index 0000000..f558ef1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Pot.PotWeapon/FireCannon.cs @@ -0,0 +1,124 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Pot.PotWeapon; + +public class FireCannon : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject projectilePrefab; + + public static float selfForce = 1000f; + + public static int grenadeCountMax = 3; + + public static float damageCoefficient; + + public static float fireDuration = 1f; + + public static float baseDuration = 2f; + + public static float minSpread = 0f; + + public static float maxSpread = 5f; + + public static float arcAngle = 5f; + + private Ray aimRay; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + private void FireBullet(string targetMuzzle) + { + aimRay = GetAimRay(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(targetMuzzle); + if ((bool)transform) + { + base.rigidbody.AddForceAtPosition(transform.forward * selfForce, transform.position, ForceMode.Impulse); + } + } + } + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + float x = Random.Range(minSpread, maxSpread); + float z = Random.Range(0f, 360f); + Vector3 up = Vector3.up; + Vector3 axis = Vector3.Cross(up, aimRay.direction); + Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward); + float y = vector.y; + vector.y = 0f; + float angle = Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f; + float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f + arcAngle; + Vector3 forward = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * aimRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + aimRay = GetAimRay(); + StartAimMode(aimRay); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + fireTimer -= GetDeltaTime(); + float num = fireDuration / attackSpeedStat / (float)grenadeCountMax; + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + fireTimer += num; + if (grenadeCount % 2 == 0) + { + FireBullet("MuzzleLeft"); + PlayCrossfade("Gesture, Left Cannon", "FireGrenadeLeft", 0.1f); + } + else + { + FireBullet("MuzzleRight"); + PlayCrossfade("Gesture, Right Cannon", "FireGrenadeRight", 0.1f); + } + grenadeCount++; + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Pounder/Pound.cs b/ilspy_dump/ror2_csproj/EntityStates.Pounder/Pound.cs new file mode 100644 index 0000000..e7d5eb5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Pounder/Pound.cs @@ -0,0 +1,67 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Pounder; + +public class Pound : BaseState +{ + public static float blastRadius; + + public static float blastProcCoefficient; + + public static float blastForce; + + public static float blastFrequency; + + public static float duration; + + public static GameObject blastEffectPrefab; + + private ProjectileDamage projectileDamage; + + private float poundTimer; + + private static int PoundStateHash = Animator.StringToHash("Pound"); + + public override void OnEnter() + { + base.OnEnter(); + projectileDamage = GetComponent(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + poundTimer -= GetDeltaTime(); + if (poundTimer <= 0f && (bool)base.projectileController.owner) + { + poundTimer += 1f / blastFrequency; + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.projectileController.owner; + blastAttack.baseDamage = projectileDamage.damage; + blastAttack.baseForce = blastForce; + blastAttack.crit = projectileDamage.crit; + blastAttack.damageType = projectileDamage.damageType; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.position = base.transform.position; + blastAttack.radius = blastRadius; + blastAttack.teamIndex = base.projectileController.teamFilter.teamIndex; + blastAttack.Fire(); + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = blastRadius + }, transmit: true); + } + PlayAnimation("Base", PoundStateHash); + } + if (NetworkServer.active && base.fixedAge > duration) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Pounder/Spawn.cs b/ilspy_dump/ror2_csproj/EntityStates.Pounder/Spawn.cs new file mode 100644 index 0000000..6c1e7bc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Pounder/Spawn.cs @@ -0,0 +1,47 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Pounder; + +public class Spawn : BaseState +{ + public static GameObject spawnPrefab; + + public static float baseDuration; + + public static string spawnSoundString; + + private float duration; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(spawnSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(spawnPrefab, base.gameObject, "Feet", transmit: false); + PlayAnimation("Base", SpawnStateHash, SpawnParamHash, duration); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/CountDown.cs b/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/CountDown.cs new file mode 100644 index 0000000..bb1dcc3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/CountDown.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.QuestVolatileBattery; + +public class CountDown : QuestVolatileBatteryBaseState +{ + public static float duration; + + public static GameObject vfxPrefab; + + public static float explosionRadius; + + public static GameObject explosionEffectPrefab; + + private GameObject[] vfxInstances = Array.Empty(); + + private bool detonated; + + public override void OnEnter() + { + base.OnEnter(); + if (!vfxPrefab || !base.attachedCharacterModel) + { + return; + } + List equipmentDisplayObjects = base.attachedCharacterModel.GetEquipmentDisplayObjects(RoR2Content.Equipment.QuestVolatileBattery.equipmentIndex); + if (equipmentDisplayObjects.Count > 0) + { + vfxInstances = new GameObject[equipmentDisplayObjects.Count]; + for (int i = 0; i < vfxInstances.Length; i++) + { + GameObject gameObject = UnityEngine.Object.Instantiate(vfxPrefab, equipmentDisplayObjects[i].transform); + gameObject.transform.localPosition = Vector3.zero; + gameObject.transform.localRotation = Quaternion.identity; + vfxInstances[i] = gameObject; + } + } + } + + public override void OnExit() + { + GameObject[] array = vfxInstances; + for (int i = 0; i < array.Length; i++) + { + EntityState.Destroy(array[i]); + } + vfxInstances = Array.Empty(); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + FixedUpdateServer(); + } + } + + private void FixedUpdateServer() + { + if (base.fixedAge >= duration && !detonated) + { + detonated = true; + Detonate(); + } + } + + public void Detonate() + { + if ((bool)base.networkedBodyAttachment.attachedBody) + { + Vector3 corePosition = base.networkedBodyAttachment.attachedBody.corePosition; + float baseDamage = 0f; + if ((bool)base.attachedHealthComponent) + { + baseDamage = base.attachedHealthComponent.fullCombinedHealth * 3f; + } + EffectManager.SpawnEffect(explosionEffectPrefab, new EffectData + { + origin = corePosition, + scale = explosionRadius + }, transmit: true); + BlastAttack blastAttack = new BlastAttack(); + blastAttack.position = corePosition + UnityEngine.Random.onUnitSphere; + blastAttack.radius = explosionRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.attacker = base.networkedBodyAttachment.attachedBodyObject; + blastAttack.inflictor = base.networkedBodyAttachment.gameObject; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.baseDamage = baseDamage; + blastAttack.baseForce = 5000f; + blastAttack.bonusForce = Vector3.zero; + blastAttack.attackerFiltering = AttackerFiltering.AlwaysHit; + blastAttack.crit = false; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = 0f; + blastAttack.teamIndex = base.networkedBodyAttachment.attachedBody.teamComponent.teamIndex; + blastAttack.Fire(); + base.networkedBodyAttachment.attachedBody.inventory.SetEquipmentIndex(EquipmentIndex.None); + outer.SetNextState(new Idle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/Monitor.cs b/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/Monitor.cs new file mode 100644 index 0000000..9586d4b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/Monitor.cs @@ -0,0 +1,32 @@ +using UnityEngine.Networking; + +namespace EntityStates.QuestVolatileBattery; + +public class Monitor : QuestVolatileBatteryBaseState +{ + private float previousHealthFraction; + + private static readonly float healthFractionDetonationThreshold = 0.5f; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + FixedUpdateServer(); + } + } + + private void FixedUpdateServer() + { + if ((bool)base.attachedHealthComponent) + { + float combinedHealthFraction = base.attachedHealthComponent.combinedHealthFraction; + if (combinedHealthFraction <= healthFractionDetonationThreshold && healthFractionDetonationThreshold < previousHealthFraction) + { + outer.SetNextState(new CountDown()); + } + previousHealthFraction = combinedHealthFraction; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/QuestVolatileBatteryBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/QuestVolatileBatteryBaseState.cs new file mode 100644 index 0000000..64fcf69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.QuestVolatileBattery/QuestVolatileBatteryBaseState.cs @@ -0,0 +1,37 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.QuestVolatileBattery; + +public class QuestVolatileBatteryBaseState : BaseState +{ + protected NetworkedBodyAttachment networkedBodyAttachment { get; private set; } + + protected HealthComponent attachedHealthComponent { get; private set; } + + protected CharacterModel attachedCharacterModel { get; private set; } + + protected Transform[] displays { get; private set; } = Array.Empty(); + + + public override void OnEnter() + { + base.OnEnter(); + networkedBodyAttachment = GetComponent(); + if (!networkedBodyAttachment || !networkedBodyAttachment.attachedBody) + { + return; + } + attachedHealthComponent = networkedBodyAttachment.attachedBody.healthComponent; + ModelLocator modelLocator = networkedBodyAttachment.attachedBody.modelLocator; + if ((bool)modelLocator) + { + Transform modelTransform = modelLocator.modelTransform; + if ((bool)modelTransform) + { + attachedCharacterModel = modelTransform.GetComponent(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseBackpack.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseBackpack.cs new file mode 100644 index 0000000..c42c9dc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseBackpack.cs @@ -0,0 +1,67 @@ +using RoR2; +using RoR2.Audio; +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public abstract class BaseBackpack : BaseState +{ + [SerializeField] + public LoopSoundDef loopSoundDef; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string mecanimBoolName; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + protected bool isSoundScaledByAttackSpeed; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)loopSoundDef) + { + if (isSoundScaledByAttackSpeed) + { + loopPtr = LoopSoundManager.PlaySoundLoopLocalRtpc(base.gameObject, loopSoundDef, "attackSpeed", Util.CalculateAttackSpeedRtpcValue(attackSpeedStat)); + } + else + { + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSoundDef); + } + } + if (!string.IsNullOrEmpty(enterSoundString)) + { + if (isSoundScaledByAttackSpeed) + { + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + } + else + { + Util.PlaySound(enterSoundString, base.gameObject); + } + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator && !string.IsNullOrEmpty(mecanimBoolName)) + { + modelAnimator.SetBool(mecanimBoolName, value: true); + } + } + + public override void OnExit() + { + if (loopPtr.isValid) + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator && !string.IsNullOrEmpty(mecanimBoolName)) + { + modelAnimator.SetBool(mecanimBoolName, value: false); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseCharged.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseCharged.cs new file mode 100644 index 0000000..3bdf2ae --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseCharged.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.HudOverlay; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public abstract class BaseCharged : BaseBackpack +{ + [SerializeField] + public float duration; + + [SerializeField] + public SkillDef primaryOverride; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public GameObject overlayPrefab; + + [SerializeField] + public string overlayChildLocatorEntry; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private OverlayController overlayController; + + private GenericSkill primarySkill; + + private List fillUiList = new List(); + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + SkillLocator component = base.gameObject.GetComponent(); + if ((bool)component && (bool)component.primary) + { + primarySkill = component.primary; + primarySkill.SetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + OverlayCreationParams overlayCreationParams = default(OverlayCreationParams); + overlayCreationParams.prefab = overlayPrefab; + overlayCreationParams.childLocatorEntry = overlayChildLocatorEntry; + OverlayCreationParams overlayCreationParams2 = overlayCreationParams; + overlayController = HudOverlayManager.AddOverlay(base.gameObject, overlayCreationParams2); + overlayController.onInstanceAdded += OnOverlayInstanceAdded; + overlayController.onInstanceRemove += OnOverlayInstanceRemoved; + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.PrioritySkill); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (duration > 0f) + { + foreach (ImageFillController fillUi in fillUiList) + { + fillUi.SetTValue(1f - base.fixedAge / duration); + } + } + if (base.fixedAge >= duration) + { + outer.SetNextState(InstantiateExpiredState()); + } + base.characterBody.SetAimTimer(3f); + } + + public override void OnExit() + { + crosshairOverrideRequest?.Dispose(); + if (overlayController != null) + { + overlayController.onInstanceAdded -= OnOverlayInstanceAdded; + overlayController.onInstanceRemove -= OnOverlayInstanceRemoved; + fillUiList.Clear(); + HudOverlayManager.RemoveOverlay(overlayController); + } + if ((bool)base.skillLocator) + { + primarySkill.UnsetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } + + protected abstract EntityState InstantiateExpiredState(); + + private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) + { + fillUiList.Add(instance.GetComponent()); + } + + private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) + { + fillUiList.Remove(instance.GetComponent()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseCharging.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseCharging.cs new file mode 100644 index 0000000..a3cfcfa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseCharging.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using RoR2.HudOverlay; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public abstract class BaseCharging : BaseBackpack +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public GameObject overlayPrefab; + + [SerializeField] + public string overlayChildLocatorEntry; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private OverlayController overlayController; + + private List fillUiList = new List(); + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private float duration; + + public override void OnEnter() + { + isSoundScaledByAttackSpeed = true; + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + OverlayCreationParams overlayCreationParams = default(OverlayCreationParams); + overlayCreationParams.prefab = overlayPrefab; + overlayCreationParams.childLocatorEntry = overlayChildLocatorEntry; + OverlayCreationParams overlayCreationParams2 = overlayCreationParams; + overlayController = HudOverlayManager.AddOverlay(base.gameObject, overlayCreationParams2); + overlayController.onInstanceAdded += OnOverlayInstanceAdded; + overlayController.onInstanceRemove += OnOverlayInstanceRemoved; + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.PrioritySkill); + } + } + + public override void OnExit() + { + crosshairOverrideRequest?.Dispose(); + if (overlayController != null) + { + overlayController.onInstanceAdded -= OnOverlayInstanceAdded; + overlayController.onInstanceRemove -= OnOverlayInstanceRemoved; + fillUiList.Clear(); + HudOverlayManager.RemoveOverlay(overlayController); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (duration > 0f) + { + foreach (ImageFillController fillUi in fillUiList) + { + fillUi.SetTValue(base.fixedAge / duration); + } + } + if (base.fixedAge >= duration) + { + outer.SetNextState(InstantiateChargedState()); + } + } + + protected abstract EntityState InstantiateChargedState(); + + private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) + { + fillUiList.Add(instance.GetComponent()); + } + + private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) + { + fillUiList.Remove(instance.GetComponent()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseExpired.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseExpired.cs new file mode 100644 index 0000000..bdce3ae --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseExpired.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public abstract class BaseExpired : BaseBackpack +{ + [SerializeField] + public float duration; + + [SerializeField] + public bool forceShieldRegen; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if (forceShieldRegen) + { + base.characterBody?.healthComponent?.ForceShieldRegen(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(InstantiateNextState()); + } + } + + protected abstract EntityState InstantiateNextState(); + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseOnline.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseOnline.cs new file mode 100644 index 0000000..135fa6d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/BaseOnline.cs @@ -0,0 +1,62 @@ +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public abstract class BaseOnline : BaseBackpack +{ + [SerializeField] + public SkillDef requiredSkillDef; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string cooldownParamName; + + private int animationStateHash; + + private int cooldownParamHash; + + private Animator animator; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + animator = GetModelAnimator(); + cooldownParamHash = Animator.StringToHash(cooldownParamName); + animationStateHash = Animator.StringToHash(animationStateName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((object)base.skillLocator.special.skillDef != requiredSkillDef) + { + outer.SetNextState(new Disconnected()); + } + else if ((bool)animator) + { + float num = base.skillLocator.special.CalculateFinalRechargeInterval(); + float value = 0f; + if (num > 0f) + { + value = base.skillLocator.special.cooldownRemaining / num; + } + animator.SetFloat(cooldownParamHash, value); + } + } + + public override void OnExit() + { + if ((bool)animator) + { + animator.SetFloat(cooldownParamHash, 0f); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargedCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargedCryo.cs new file mode 100644 index 0000000..f9daec4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargedCryo.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Backpack; + +public class ChargedCryo : BaseCharged +{ + protected override EntityState InstantiateExpiredState() + { + return new ExpiredCryo(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargedSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargedSuper.cs new file mode 100644 index 0000000..a1fcdd1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargedSuper.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Backpack; + +public class ChargedSuper : BaseCharged +{ + protected override EntityState InstantiateExpiredState() + { + return new ExpiredSuper(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargingCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargingCryo.cs new file mode 100644 index 0000000..ca6ba9b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargingCryo.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Backpack; + +public class ChargingCryo : BaseCharging +{ + protected override EntityState InstantiateChargedState() + { + return new ChargedCryo(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargingSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargingSuper.cs new file mode 100644 index 0000000..1351ea5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ChargingSuper.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Backpack; + +public class ChargingSuper : BaseCharging +{ + protected override EntityState InstantiateChargedState() + { + return new ChargedSuper(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Disconnected.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Disconnected.cs new file mode 100644 index 0000000..1b41349 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Disconnected.cs @@ -0,0 +1,38 @@ +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public class Disconnected : BaseBackpack +{ + [SerializeField] + public SkillDef superSkillDef; + + [SerializeField] + public SkillDef cryoSkillDef; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((object)base.skillLocator.special.skillDef == superSkillDef) + { + outer.SetNextState(new OnlineSuper()); + } + else if ((object)base.skillLocator.special.skillDef == cryoSkillDef) + { + outer.SetNextState(new OnlineCryo()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ExpiredCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ExpiredCryo.cs new file mode 100644 index 0000000..f3d1078 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ExpiredCryo.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Backpack; + +public class ExpiredCryo : BaseExpired +{ + protected override EntityState InstantiateNextState() + { + return new OnlineCryo(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ExpiredSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ExpiredSuper.cs new file mode 100644 index 0000000..76bc29d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/ExpiredSuper.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Backpack; + +public class ExpiredSuper : BaseExpired +{ + protected override EntityState InstantiateNextState() + { + return new OnlineSuper(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Offline.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Offline.cs new file mode 100644 index 0000000..3a254c8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Offline.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using RoR2.HudOverlay; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public class Offline : BaseBackpack +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public GameObject overlayPrefab; + + [SerializeField] + public string overlayChildLocatorEntry; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private OverlayController overlayController; + + private List fillUiList = new List(); + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + OverlayCreationParams overlayCreationParams = default(OverlayCreationParams); + overlayCreationParams.prefab = overlayPrefab; + overlayCreationParams.childLocatorEntry = overlayChildLocatorEntry; + OverlayCreationParams overlayCreationParams2 = overlayCreationParams; + overlayController = HudOverlayManager.AddOverlay(base.gameObject, overlayCreationParams2); + overlayController.onInstanceAdded += OnOverlayInstanceAdded; + overlayController.onInstanceRemove += OnOverlayInstanceRemoved; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new Reboot()); + } + if (!(duration > 0f)) + { + return; + } + foreach (ImageFillController fillUi in fillUiList) + { + fillUi.SetTValue(base.fixedAge / duration); + } + } + + public override void OnExit() + { + crosshairOverrideRequest?.Dispose(); + if (overlayController != null) + { + overlayController.onInstanceAdded -= OnOverlayInstanceAdded; + overlayController.onInstanceRemove -= OnOverlayInstanceRemoved; + fillUiList.Clear(); + HudOverlayManager.RemoveOverlay(overlayController); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } + + private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) + { + fillUiList.Add(instance.GetComponent()); + } + + private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) + { + fillUiList.Remove(instance.GetComponent()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/OnlineCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/OnlineCryo.cs new file mode 100644 index 0000000..56d8f32 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/OnlineCryo.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Backpack; + +public class OnlineCryo : BaseOnline +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/OnlineSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/OnlineSuper.cs new file mode 100644 index 0000000..d63d72f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/OnlineSuper.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Backpack; + +public class OnlineSuper : BaseOnline +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Reboot.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Reboot.cs new file mode 100644 index 0000000..6de27d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/Reboot.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public class Reboot : BaseBackpack +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new OnlineSuper()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/UseCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/UseCryo.cs new file mode 100644 index 0000000..6a34fe9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Backpack/UseCryo.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +namespace EntityStates.Railgunner.Backpack; + +public class UseCryo : BaseBackpack +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new OnlineCryo()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/BoostConfirm.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/BoostConfirm.cs new file mode 100644 index 0000000..4bca78d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/BoostConfirm.cs @@ -0,0 +1,79 @@ +using RoR2; +using RoR2.HudOverlay; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Reload; + +public class BoostConfirm : EntityState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + public OverlayController overlayController; + + private GenericSkill primarySkill; + + public SkillDef primaryOverride; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + if (overlayController == null) + { + return; + } + foreach (GameObject instances in overlayController.instancesList) + { + ActiveReloadBarController component = instances.GetComponent(); + if ((bool)component) + { + component.SetWasWindowHit(wasWindowHit: true); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new Boosted()); + } + } + + public override void OnExit() + { + if (overlayController != null) + { + HudOverlayManager.RemoveOverlay(overlayController); + } + if ((bool)primarySkill) + { + primarySkill.UnsetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + base.OnExit(); + } + + public void OverridePrimary(GenericSkill skill, SkillDef overrideDef) + { + primarySkill = skill; + primaryOverride = overrideDef; + primarySkill.SetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Boosted.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Boosted.cs new file mode 100644 index 0000000..cb88ceb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Boosted.cs @@ -0,0 +1,49 @@ +using RoR2; +using RoR2.HudOverlay; +using UnityEngine; + +namespace EntityStates.Railgunner.Reload; + +public class Boosted : BaseState +{ + [SerializeField] + public float bonusDamageCoefficient; + + [SerializeField] + public string boostConsumeSoundString; + + [SerializeField] + public GameObject overlayPrefab; + + [SerializeField] + public string overlayChildLocatorEntry; + + private OverlayController overlayController; + + public float GetBonusDamage() + { + return bonusDamageCoefficient * damageStat; + } + + public void ConsumeBoost(bool queueReload) + { + Util.PlaySound(boostConsumeSoundString, base.gameObject); + outer.SetNextState(new Waiting(queueReload)); + } + + public override void OnEnter() + { + base.OnEnter(); + OverlayCreationParams overlayCreationParams = default(OverlayCreationParams); + overlayCreationParams.prefab = overlayPrefab; + overlayCreationParams.childLocatorEntry = overlayChildLocatorEntry; + OverlayCreationParams overlayCreationParams2 = overlayCreationParams; + overlayController = HudOverlayManager.AddOverlay(base.gameObject, overlayCreationParams2); + } + + public override void OnExit() + { + HudOverlayManager.RemoveOverlay(overlayController); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Reloading.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Reloading.cs new file mode 100644 index 0000000..9120b7e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Reloading.cs @@ -0,0 +1,203 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Audio; +using RoR2.HudOverlay; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Reload; + +public class Reloading : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float boostWindowDelay; + + [SerializeField] + public float boostWindowDuration; + + [SerializeField] + public float boostGracePeriod; + + [SerializeField] + public SkillDef primaryOverride; + + [SerializeField] + public GameObject overlayPrefab; + + [SerializeField] + public string overlayChildLocatorEntry; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public LoopSoundDef loopSoundDef; + + [SerializeField] + public string endNoBoostSoundString; + + [SerializeField] + public string failSoundString; + + private float duration; + + private float adjustedBoostWindowDelay; + + private float adjustedBoostWindowDuration; + + private GenericSkill primarySkill; + + private OverlayController overlayController; + + private List reloadUiList = new List(); + + private bool hasAttempted; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + public bool AttemptBoost() + { + if (IsInBoostWindow()) + { + outer.SetNextState(new BoostConfirm()); + return true; + } + foreach (ActiveReloadBarController reloadUi in reloadUiList) + { + reloadUi.SetWasFailure(wasFailure: true); + } + return false; + } + + public override void OnEnter() + { + base.OnEnter(); + float num = boostWindowDelay + boostWindowDuration; + float num2 = baseDuration - num; + duration = num + num2 / attackSpeedStat; + adjustedBoostWindowDelay = Mathf.Min(boostWindowDelay / baseDuration * duration, boostWindowDelay); + adjustedBoostWindowDuration = Mathf.Max((boostWindowDelay + boostWindowDuration) / baseDuration * duration, num) - adjustedBoostWindowDelay; + if ((bool)loopSoundDef) + { + loopPtr = LoopSoundManager.PlaySoundLoopLocalRtpc(base.gameObject, loopSoundDef, "attackSpeed", Util.CalculateAttackSpeedRtpcValue(attackSpeedStat)); + } + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + SkillLocator component = base.gameObject.GetComponent(); + if ((bool)component && (bool)component.primary) + { + primarySkill = component.primary; + primarySkill.SetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + OverlayCreationParams overlayCreationParams = default(OverlayCreationParams); + overlayCreationParams.prefab = overlayPrefab; + overlayCreationParams.childLocatorEntry = overlayChildLocatorEntry; + OverlayCreationParams overlayCreationParams2 = overlayCreationParams; + overlayController = HudOverlayManager.AddOverlay(base.gameObject, overlayCreationParams2); + overlayController.onInstanceAdded += OnOverlayInstanceAdded; + overlayController.onInstanceRemove += OnOverlayInstanceRemoved; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float num = ((duration > 0f) ? (base.fixedAge / duration) : 0f); + foreach (ActiveReloadBarController reloadUi in reloadUiList) + { + reloadUi.SetTValue(num); + reloadUi.SetIsWindowActive(IsInBoostWindow()); + } + if (duration <= 0f || num >= 1f) + { + Util.PlaySound(endNoBoostSoundString, base.gameObject); + outer.SetNextState(new Waiting()); + } + if ((bool)base.inputBank && base.inputBank.skill1.justPressed && !hasAttempted) + { + hasAttempted = true; + if (!AttemptBoost()) + { + Util.PlaySound(failSoundString, base.gameObject); + } + } + } + + public override void OnExit() + { + if (overlayController != null) + { + overlayController.onInstanceAdded -= OnOverlayInstanceAdded; + overlayController.onInstanceRemove -= OnOverlayInstanceRemoved; + reloadUiList.Clear(); + } + if ((bool)base.skillLocator) + { + primarySkill.UnsetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + for (int i = 0; i < base.skillLocator.skillSlotCount; i++) + { + GenericSkill skillAtIndex = base.skillLocator.GetSkillAtIndex(i); + if ((bool)skillAtIndex) + { + RailgunSkillDef railgunSkillDef = skillAtIndex.skillDef as RailgunSkillDef; + if ((bool)railgunSkillDef && railgunSkillDef.restockOnReload) + { + skillAtIndex.stock = skillAtIndex.maxStock; + } + } + } + if (loopPtr.isValid) + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + } + base.OnExit(); + } + + public bool IsInBoostWindow() + { + if (adjustedBoostWindowDelay - base.fixedAge < boostGracePeriod) + { + return base.fixedAge - (adjustedBoostWindowDelay + adjustedBoostWindowDuration) < boostGracePeriod; + } + return false; + } + + public override void ModifyNextState(EntityState nextState) + { + if (nextState is BoostConfirm boostConfirm) + { + boostConfirm.overlayController = overlayController; + if ((bool)primarySkill) + { + boostConfirm.OverridePrimary(primarySkill, primaryOverride); + } + } + else if (overlayController != null) + { + HudOverlayManager.RemoveOverlay(overlayController); + } + } + + private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) + { + ActiveReloadBarController component = instance.GetComponent(); + float num = ((duration > 0f) ? (1f / duration) : 0f); + component.SetWindowRange(num * adjustedBoostWindowDelay, num * (adjustedBoostWindowDelay + adjustedBoostWindowDuration)); + reloadUiList.Add(component); + } + + private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) + { + ActiveReloadBarController component = instance.GetComponent(); + reloadUiList.Remove(component); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Waiting.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Waiting.cs new file mode 100644 index 0000000..ade82c9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Reload/Waiting.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using EntityStates.Railgunner.Backpack; +using RoR2; +using RoR2.Skills; + +namespace EntityStates.Railgunner.Reload; + +public class Waiting : EntityState +{ + private const string backpackStateMachineName = "Backpack"; + + private const string scopeStateMachineName = "Scope"; + + private List restockOnReloadList = new List(); + + private EntityStateMachine backpackStateMachine; + + private EntityStateMachine scopeStateMachine; + + private bool isReloadQueued; + + public Waiting() + { + isReloadQueued = false; + } + + public Waiting(bool queueReload) + { + isReloadQueued = queueReload; + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.skillLocator) + { + for (int i = 0; i < base.skillLocator.skillSlotCount; i++) + { + GenericSkill skillAtIndex = base.skillLocator.GetSkillAtIndex(i); + if ((bool)skillAtIndex) + { + skillAtIndex.onSkillChanged += OnSkillChanged; + } + } + ReevaluateSkills(); + } + backpackStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Backpack"); + scopeStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Scope"); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!isReloadQueued) + { + foreach (GenericSkill restockOnReload in restockOnReloadList) + { + if (restockOnReload.stock == 0) + { + isReloadQueued = true; + break; + } + } + } + if (isReloadQueued && CanReload()) + { + outer.SetNextState(new Reloading()); + } + } + + public override void OnExit() + { + if ((bool)base.skillLocator) + { + for (int i = 0; i < base.skillLocator.skillSlotCount; i++) + { + GenericSkill skillAtIndex = base.skillLocator.GetSkillAtIndex(i); + if ((bool)skillAtIndex) + { + skillAtIndex.onSkillChanged -= OnSkillChanged; + } + } + } + base.OnExit(); + } + + public bool CanReload() + { + if (!(backpackStateMachine.state is Offline)) + { + return scopeStateMachine.IsInMainState(); + } + return false; + } + + public void QueueReload() + { + isReloadQueued = true; + } + + private void OnSkillChanged(GenericSkill skill) + { + ReevaluateSkills(); + } + + private void ReevaluateSkills() + { + restockOnReloadList.Clear(); + for (int i = 0; i < base.skillLocator.skillSlotCount; i++) + { + GenericSkill skillAtIndex = base.skillLocator.GetSkillAtIndex(i); + if ((bool)skillAtIndex) + { + RailgunSkillDef railgunSkillDef = skillAtIndex.skillDef as RailgunSkillDef; + if ((bool)railgunSkillDef && railgunSkillDef.restockOnReload) + { + restockOnReloadList.Add(skillAtIndex); + } + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/ActiveScopeHeavy.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/ActiveScopeHeavy.cs new file mode 100644 index 0000000..372f305 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/ActiveScopeHeavy.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Scope; + +public class ActiveScopeHeavy : BaseActive +{ + protected override BaseWindDown GetNextState() + { + return new WindDownScopeHeavy(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/ActiveScopeLight.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/ActiveScopeLight.cs new file mode 100644 index 0000000..86ae245 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/ActiveScopeLight.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Scope; + +public class ActiveScopeLight : BaseActive +{ + protected override BaseWindDown GetNextState() + { + return new WindDownScopeLight(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseActive.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseActive.cs new file mode 100644 index 0000000..c33f5f3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseActive.cs @@ -0,0 +1,79 @@ +using RoR2; +using RoR2.Audio; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Railgunner.Scope; + +public class BaseActive : BaseScopeState +{ + [SerializeField] + public SkillDef primaryOverride; + + [SerializeField] + public LoopSoundDef loopSound; + + private GenericSkill overriddenSkill; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + public override void OnEnter() + { + base.OnEnter(); + SetScopeAlpha(1f); + StartScopeParamsOverride(0f); + GenericSkill genericSkill = base.skillLocator?.primary; + if ((bool)genericSkill) + { + TryOverrideSkill(genericSkill); + genericSkill.onSkillChanged += TryOverrideSkill; + } + if (base.isAuthority) + { + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSound); + } + } + + public override void OnExit() + { + if (loopPtr.isValid) + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + } + GenericSkill genericSkill = base.skillLocator?.primary; + if ((bool)genericSkill) + { + genericSkill.onSkillChanged -= TryOverrideSkill; + } + if ((bool)overriddenSkill) + { + overriddenSkill.UnsetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + EndScopeParamsOverride(0f); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (!IsKeyDownAuthority() || base.characterBody.isSprinting)) + { + outer.SetNextState(GetNextState()); + } + } + + private void TryOverrideSkill(GenericSkill skill) + { + if ((bool)skill && !overriddenSkill && !skill.HasSkillOverrideOfPriority(GenericSkill.SkillOverridePriority.Contextual)) + { + overriddenSkill = skill; + overriddenSkill.SetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + overriddenSkill.stock = base.skillLocator.secondary.stock; + } + } + + protected virtual BaseWindDown GetNextState() + { + return new BaseWindDown(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseScopeState.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseScopeState.cs new file mode 100644 index 0000000..624920e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseScopeState.cs @@ -0,0 +1,117 @@ +using RoR2; +using RoR2.HudOverlay; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Scope; + +public class BaseScopeState : BaseSkillState +{ + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public GameObject scopeOverlayPrefab; + + [SerializeField] + public CharacterCameraParams cameraParams; + + [SerializeField] + public float cameraOverridePriority; + + public static string mecanimBoolName; + + private OverlayController overlayController; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private CameraTargetParams.CameraParamsOverrideHandle cameraParamsOverrideHandle; + + public static bool inScope; + + public override void OnEnter() + { + base.OnEnter(); + overlayController = HudOverlayManager.AddOverlay(base.gameObject, new OverlayCreationParams + { + prefab = scopeOverlayPrefab, + childLocatorEntry = "ScopeContainer" + }); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(mecanimBoolName, value: true); + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + inScope = true; + } + + public override void OnExit() + { + inScope = false; + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(mecanimBoolName, value: false); + } + RemoveOverlay(0f); + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + protected void SetScopeAlpha(float alpha) + { + if (overlayController != null) + { + overlayController.alpha = alpha; + } + } + + protected void RemoveOverlay(float transitionDuration) + { + if (overlayController != null) + { + HudOverlayManager.RemoveOverlay(overlayController); + overlayController = null; + } + } + + protected void StartScopeParamsOverride(float transitionDuration) + { + if (!cameraParamsOverrideHandle.isValid) + { + cameraParamsOverrideHandle = base.cameraTargetParams.AddParamsOverride(new CameraTargetParams.CameraParamsOverrideRequest + { + cameraParamsData = cameraParams.data, + priority = cameraOverridePriority + }, transitionDuration); + } + } + + protected void EndScopeParamsOverride(float transitionDuration) + { + if (cameraParamsOverrideHandle.isValid) + { + base.cameraTargetParams.RemoveParamsOverride(cameraParamsOverrideHandle, transitionDuration); + cameraParamsOverrideHandle = default(CameraTargetParams.CameraParamsOverrideHandle); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected virtual CharacterCameraParams GetCameraParams() + { + return cameraParams; + } + + protected virtual float GetScopeEntryDuration() + { + return 0f; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseWindDown.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseWindDown.cs new file mode 100644 index 0000000..6235a51 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseWindDown.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Railgunner.Scope; + +public class BaseWindDown : BaseScopeState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string enterSoundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + SetScopeAlpha(1f); + RemoveOverlay(duration); + StartScopeParamsOverride(0f); + EndScopeParamsOverride(duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override void Update() + { + base.Update(); + SetScopeAlpha(1f - Mathf.Clamp01(base.age / duration)); + } + + protected override CharacterCameraParams GetCameraParams() + { + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseWindUp.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseWindUp.cs new file mode 100644 index 0000000..22462c5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/BaseWindUp.cs @@ -0,0 +1,61 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Railgunner.Scope; + +public class BaseWindUp : BaseScopeState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string enterSoundString; + + private float duration; + + public override void OnEnter() + { + duration = baseDuration; + base.OnEnter(); + SetScopeAlpha(0f); + StartScopeParamsOverride(duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void OnExit() + { + EndScopeParamsOverride(0f); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + BaseActive nextState = GetNextState(); + nextState.activatorSkillSlot = base.activatorSkillSlot; + outer.SetNextState(nextState); + } + } + + public override void Update() + { + base.Update(); + SetScopeAlpha(Mathf.Clamp01(base.age / duration)); + } + + protected virtual BaseActive GetNextState() + { + return new BaseActive(); + } + + protected override float GetScopeEntryDuration() + { + return duration; + } + + public override void ModifyNextState(EntityState nextState) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindDownScopeHeavy.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindDownScopeHeavy.cs new file mode 100644 index 0000000..6674ba3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindDownScopeHeavy.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Scope; + +public class WindDownScopeHeavy : BaseWindDown +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindDownScopeLight.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindDownScopeLight.cs new file mode 100644 index 0000000..8a8224f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindDownScopeLight.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Scope; + +public class WindDownScopeLight : BaseWindDown +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindUpScopeHeavy.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindUpScopeHeavy.cs new file mode 100644 index 0000000..bb4dcd5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindUpScopeHeavy.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Scope; + +public class WindUpScopeHeavy : BaseWindUp +{ + protected override BaseActive GetNextState() + { + return new ActiveScopeHeavy(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindUpScopeLight.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindUpScopeLight.cs new file mode 100644 index 0000000..68ac114 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Scope/WindUpScopeLight.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Scope; + +public class WindUpScopeLight : BaseWindUp +{ + protected override BaseActive GetNextState() + { + return new ActiveScopeLight(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ActiveReload.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ActiveReload.cs new file mode 100644 index 0000000..132efd9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ActiveReload.cs @@ -0,0 +1,49 @@ +using EntityStates.Railgunner.Reload; +using RoR2; +using UnityEngine; + +namespace EntityStates.Railgunner.Weapon; + +public class ActiveReload : BaseState +{ + private const string reloadStateMachineName = "Reload"; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + EntityStateMachine entityStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Reload"); + if ((bool)entityStateMachine && entityStateMachine.state is Reloading reloading) + { + reloading.AttemptBoost(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseChargeSnipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseChargeSnipe.cs new file mode 100644 index 0000000..3924819 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseChargeSnipe.cs @@ -0,0 +1,56 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Railgunner.Weapon; + +public abstract class BaseChargeSnipe : BaseState, IBaseWeaponState +{ + private const string backpackStateMachineName = "Backpack"; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + EntityStateMachine entityStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Backpack"); + if ((bool)entityStateMachine) + { + entityStateMachine.SetNextState(InstantiateBackpackState()); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public bool CanScope() + { + return false; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + protected abstract EntityState InstantiateBackpackState(); +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseFireMine.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseFireMine.cs new file mode 100644 index 0000000..3256d53 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseFireMine.cs @@ -0,0 +1,84 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Railgunner.Weapon; + +public class BaseFireMine : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float baseCrossfadeDuration; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + float crossfadeDuration = baseCrossfadeDuration / attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + if ((bool)GetModelAnimator()) + { + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateParam, duration, crossfadeDuration); + } + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseFireSnipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseFireSnipe.cs new file mode 100644 index 0000000..e10938b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseFireSnipe.cs @@ -0,0 +1,155 @@ +using System; +using EntityStates.Railgunner.Reload; +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Weapon; + +public abstract class BaseFireSnipe : GenericBulletBaseState, IBaseWeaponState +{ + private const string reloadStateMachineName = "Reload"; + + private const string backpackStateMachineName = "Backpack"; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public bool useSecondaryStocks; + + [SerializeField] + public bool queueReload; + + [SerializeField] + [Header("Projectile")] + public float critDamageMultiplier; + + [SerializeField] + public float selfKnockbackForce; + + [SerializeField] + public bool isPiercing; + + [SerializeField] + public float piercingDamageCoefficientPerTarget; + + [SerializeField] + public float trajectoryAimAssistMultiplier = 0.3f; + + [Header("Animation")] + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private bool wasMiss; + + private bool wasAtLeastOneWeakpoint; + + public static event Action onWeakPointHit; + + public static event Action onWeakPointMissed; + + public static event Action onFireSnipe; + + public override void OnEnter() + { + wasMiss = true; + BaseFireSnipe.onFireSnipe?.Invoke(this); + base.OnEnter(); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + if (base.isAuthority && useSecondaryStocks && (bool)base.skillLocator && (bool)base.skillLocator.secondary) + { + base.skillLocator.secondary.DeductStock(1); + } + } + + public override void OnExit() + { + if (base.isAuthority && (wasMiss || (!wasAtLeastOneWeakpoint && !wasMiss))) + { + BaseFireSnipe.onWeakPointMissed?.Invoke(); + } + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + protected override void ModifyBullet(BulletAttack bulletAttack) + { + bulletAttack.sniper = true; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + EntityStateMachine entityStateMachine = EntityStateMachine.FindByCustomName(base.gameObject, "Reload"); + if ((bool)entityStateMachine) + { + if (entityStateMachine.state is Boosted boosted) + { + bulletAttack.damage += boosted.GetBonusDamage(); + boosted.ConsumeBoost(queueReload); + } + else if (queueReload && entityStateMachine.state is Waiting waiting) + { + waiting.QueueReload(); + } + } + if (isPiercing) + { + bulletAttack.stopperMask = LayerIndex.world.mask; + } + bulletAttack.modifyOutgoingDamageCallback = delegate(BulletAttack _bulletAttack, ref BulletAttack.BulletHit hitInfo, DamageInfo damageInfo) + { + _bulletAttack.damage *= piercingDamageCoefficientPerTarget; + wasMiss = false; + if (damageInfo.crit) + { + damageInfo.damage *= critDamageMultiplier; + if ((bool)hitInfo.hitHurtBox && (bool)hitInfo.hitHurtBox.healthComponent && (bool)hitInfo.hitHurtBox.healthComponent.body && hitInfo.hitHurtBox.healthComponent.body.teamComponent.teamIndex != base.characterBody.teamComponent.teamIndex) + { + BaseFireSnipe.onWeakPointHit?.Invoke(damageInfo); + wasAtLeastOneWeakpoint = true; + } + } + }; + EntityStateMachine entityStateMachine2 = EntityStateMachine.FindByCustomName(base.gameObject, "Backpack"); + EntityState entityState = InstantiateBackpackState(); + if ((bool)entityStateMachine2 && entityState != null) + { + entityStateMachine2.SetNextState(entityState); + } + bulletAttack.trajectoryAimAssistMultiplier = trajectoryAimAssistMultiplier; + } + + protected override void OnFireBulletAuthority(Ray aimRay) + { + base.characterBody.characterMotor.ApplyForce((0f - selfKnockbackForce) * aimRay.direction); + } + + protected override void PlayFireAnimation() + { + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + } + + public bool CanScope() + { + return true; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + protected virtual EntityState InstantiateBackpackState() + { + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseWindupSnipe.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseWindupSnipe.cs new file mode 100644 index 0000000..63b715b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/BaseWindupSnipe.cs @@ -0,0 +1,93 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Railgunner.Weapon; + +public abstract class BaseWindupSnipe : BaseState, IBaseWeaponState +{ + [SerializeField] + public float duration; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public GameObject windupEffectPrefab; + + [SerializeField] + public string windupEffectMuzzle; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private GameObject windupEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + if ((bool)windupEffectPrefab) + { + Transform transform = FindModelChild(windupEffectMuzzle); + if ((bool)transform) + { + windupEffectInstance = Object.Instantiate(windupEffectPrefab, transform.position, transform.rotation); + windupEffectInstance.transform.parent = transform; + } + } + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(base.age / duration, canOnlyIncreaseBloom: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(InstantiateNextState()); + } + } + + public override void OnExit() + { + crosshairOverrideRequest?.Dispose(); + if ((bool)windupEffectInstance) + { + EntityState.Destroy(windupEffectInstance); + } + base.OnExit(); + } + + protected abstract EntityState InstantiateNextState(); + + public bool CanScope() + { + return true; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ChargeSnipeCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ChargeSnipeCryo.cs new file mode 100644 index 0000000..7e33771 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ChargeSnipeCryo.cs @@ -0,0 +1,11 @@ +using EntityStates.Railgunner.Backpack; + +namespace EntityStates.Railgunner.Weapon; + +public class ChargeSnipeCryo : BaseChargeSnipe +{ + protected override EntityState InstantiateBackpackState() + { + return new ChargingCryo(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ChargeSnipeSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ChargeSnipeSuper.cs new file mode 100644 index 0000000..b2ec93e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/ChargeSnipeSuper.cs @@ -0,0 +1,11 @@ +using EntityStates.Railgunner.Backpack; + +namespace EntityStates.Railgunner.Weapon; + +public class ChargeSnipeSuper : BaseChargeSnipe +{ + protected override EntityState InstantiateBackpackState() + { + return new ChargingSuper(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireMineBlinding.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireMineBlinding.cs new file mode 100644 index 0000000..cb7d213 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireMineBlinding.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Weapon; + +public class FireMineBlinding : BaseFireMine +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireMineConcussive.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireMineConcussive.cs new file mode 100644 index 0000000..cedfdc1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireMineConcussive.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Weapon; + +public class FireMineConcussive : BaseFireMine +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FirePistol.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FirePistol.cs new file mode 100644 index 0000000..443472c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FirePistol.cs @@ -0,0 +1,124 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Railgunner.Weapon; + +public class FirePistol : BaseState, IBaseWeaponState +{ + [SerializeField] + public float baseDuration; + + [Header("Projectile")] + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public float spreadBloomValue; + + [SerializeField] + public float recoilYMin; + + [SerializeField] + public float recoilXMin; + + [SerializeField] + public float recoilYMax; + + [SerializeField] + public float recoilXMax; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float selfKnockbackForce; + + [SerializeField] + public float baseInaccuracyDegrees; + + [Header("Effects")] + [SerializeField] + public string muzzleName; + + [SerializeField] + public string fireSoundString; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [Header("Animation")] + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + protected float duration; + + protected virtual void FireBullet(Ray aimRay) + { + StartAimMode(aimRay); + Util.PlaySound(fireSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + AddRecoil(recoilYMin, recoilYMax, recoilXMin, recoilXMax); + if (base.isAuthority) + { + float num = 0f; + if ((bool)base.characterBody) + { + num = base.characterBody.spreadBloomAngle; + } + Quaternion quaternion = Quaternion.AngleAxis(Random.Range(0, 360), Vector3.forward); + Quaternion quaternion2 = Quaternion.AngleAxis(Random.Range(0f, baseInaccuracyDegrees + num), Vector3.left); + Quaternion rotation = Util.QuaternionSafeLookRotation(aimRay.direction, Vector3.up) * quaternion * quaternion2; + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = aimRay.origin; + fireProjectileInfo.rotation = rotation; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.force = force; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + base.characterBody.characterMotor.ApplyForce((0f - selfKnockbackForce) * aimRay.direction); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + FireBullet(GetAimRay()); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public bool CanScope() + { + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeCryo.cs new file mode 100644 index 0000000..67b57b6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeCryo.cs @@ -0,0 +1,18 @@ +using EntityStates.Railgunner.Backpack; +using RoR2; + +namespace EntityStates.Railgunner.Weapon; + +public class FireSnipeCryo : BaseFireSnipe +{ + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.damageType |= (DamageTypeCombo)DamageType.Freeze2s; + } + + protected override EntityState InstantiateBackpackState() + { + return new UseCryo(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeHeavy.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeHeavy.cs new file mode 100644 index 0000000..7235c4e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeHeavy.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Weapon; + +public class FireSnipeHeavy : BaseFireSnipe +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeLight.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeLight.cs new file mode 100644 index 0000000..858307b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeLight.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Railgunner.Weapon; + +public class FireSnipeLight : BaseFireSnipe +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeSuper.cs new file mode 100644 index 0000000..63f002f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/FireSnipeSuper.cs @@ -0,0 +1,11 @@ +using EntityStates.Railgunner.Backpack; + +namespace EntityStates.Railgunner.Weapon; + +public class FireSnipeSuper : BaseFireSnipe +{ + protected override EntityState InstantiateBackpackState() + { + return new Offline(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/IBaseWeaponState.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/IBaseWeaponState.cs new file mode 100644 index 0000000..ccbb015 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/IBaseWeaponState.cs @@ -0,0 +1,6 @@ +namespace EntityStates.Railgunner.Weapon; + +public interface IBaseWeaponState +{ + bool CanScope(); +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/WindupSnipeCryo.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/WindupSnipeCryo.cs new file mode 100644 index 0000000..bb96394 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/WindupSnipeCryo.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Weapon; + +public class WindupSnipeCryo : BaseWindupSnipe +{ + protected override EntityState InstantiateNextState() + { + return new FireSnipeCryo(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/WindupSnipeSuper.cs b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/WindupSnipeSuper.cs new file mode 100644 index 0000000..afaf32f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Railgunner.Weapon/WindupSnipeSuper.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Railgunner.Weapon; + +public class WindupSnipeSuper : BaseWindupSnipe +{ + protected override EntityState InstantiateNextState() + { + return new FireSnipeSuper(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/ChargeEyeblast.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/ChargeEyeblast.cs new file mode 100644 index 0000000..21014f4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/ChargeEyeblast.cs @@ -0,0 +1,101 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class ChargeEyeblast : BaseState +{ + public static float baseDuration = 1f; + + public static GameObject chargeEffectPrefab; + + public static string attackString; + + public static string muzzleString; + + private float duration; + + private GameObject chargeInstance; + + protected EffectManagerHelper _emh_chargeInstance; + + public override void Reset() + { + base.Reset(); + chargeInstance = null; + _emh_chargeInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Animator modelAnimator = GetModelAnimator(); + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(muzzleString); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance = _emh_chargeInstance.gameObject; + } + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + } + if ((bool)modelAnimator) + { + PlayCrossfade("Gesture, Additive", "ChargeEyeBlast", "ChargeEyeBlast.playbackRate", duration, 0.1f); + } + } + + public override void OnExit() + { + base.OnExit(); + if (_emh_chargeInstance != null && _emh_chargeInstance.OwningPool != null) + { + _emh_chargeInstance.OwningPool.ReturnObject(_emh_chargeInstance); + } + else + { + EntityState.Destroy(chargeInstance); + } + chargeInstance = null; + _emh_chargeInstance = null; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(GetNextState()); + } + } + + public virtual EntityState GetNextState() + { + return new FireEyeBlast(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/ChargeSuperEyeblast.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/ChargeSuperEyeblast.cs new file mode 100644 index 0000000..86d6878 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/ChargeSuperEyeblast.cs @@ -0,0 +1,9 @@ +namespace EntityStates.RoboBallBoss.Weapon; + +public class ChargeSuperEyeblast : ChargeEyeblast +{ + public override EntityState GetNextState() + { + return new FireSuperEyeblast(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/DeployMinions.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/DeployMinions.cs new file mode 100644 index 0000000..07304ad --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/DeployMinions.cs @@ -0,0 +1,137 @@ +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class DeployMinions : BaseState +{ + public static float baseDuration = 3.5f; + + public static string attackSoundString; + + public static string summonSoundString; + + public static int maxSummonCount = 5; + + public static float summonDuration = 3.26f; + + public static string summonMuzzleString; + + public static string spawnCard; + + private Animator animator; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private float duration; + + private float summonInterval; + + private float summonTimer; + + private int summonCount; + + private bool isSummoning; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + duration = baseDuration; + PlayCrossfade("Gesture, Additive", "DeployMinions", "DeployMinions.playbackRate", duration, 0.1f); + Util.PlaySound(attackSoundString, base.gameObject); + summonInterval = summonDuration / (float)maxSummonCount; + } + + private Transform FindTargetClosest(Vector3 point, TeamIndex enemyTeam) + { + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(enemyTeam); + float num = 99999f; + Transform result = null; + for (int i = 0; i < teamMembers.Count; i++) + { + float num2 = Vector3.SqrMagnitude(teamMembers[i].transform.position - point); + if (num2 < num) + { + num = num2; + result = teamMembers[i].transform; + } + } + return result; + } + + private void SummonMinion() + { + if (!base.characterBody || !base.characterBody.master || base.characterBody.master.GetDeployableCount(DeployableSlot.RoboBallMini) >= base.characterBody.master.GetDeployableSameSlotLimit(DeployableSlot.RoboBallMini)) + { + return; + } + Util.PlaySound(summonSoundString, base.gameObject); + if (!NetworkServer.active) + { + return; + } + Vector3 position = FindModelChild(summonMuzzleString).position; + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(LegacyResourcesAPI.Load($"SpawnCards/CharacterSpawnCards/{spawnCard}"), new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Direct, + minDistance = 0f, + maxDistance = 0f, + position = position + }, RoR2Application.rng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + GameObject gameObject = DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + if ((bool)gameObject) + { + CharacterMaster component = gameObject.GetComponent(); + Inventory component2 = gameObject.GetComponent(); + component2.SetEquipmentIndex(base.characterBody.inventory.currentEquipmentIndex); + if (base.characterBody.inventory.GetItemCount(RoR2Content.Items.Ghost) > 0) + { + component2.GiveItem(RoR2Content.Items.Ghost); + component2.GiveItem(RoR2Content.Items.HealthDecay, 30); + component2.GiveItem(RoR2Content.Items.BoostDamage, 150); + } + Deployable deployable = gameObject.AddComponent(); + deployable.onUndeploy = new UnityEvent(); + deployable.onUndeploy.AddListener(component.TrueKill); + base.characterBody.master.AddDeployable(deployable, DeployableSlot.RoboBallMini); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)animator) + { + bool flag = animator.GetFloat("DeployMinions.active") > 0.9f; + if (isSummoning) + { + summonTimer += GetDeltaTime(); + if (NetworkServer.active && summonTimer > 0f && summonCount < maxSummonCount) + { + summonCount++; + summonTimer -= summonInterval; + SummonMinion(); + } + } + isSummoning = flag; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/EnableEyebeams.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/EnableEyebeams.cs new file mode 100644 index 0000000..6224281 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/EnableEyebeams.cs @@ -0,0 +1,27 @@ +using RoR2; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class EnableEyebeams : BaseState +{ + public static float baseDuration; + + public static string soundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(soundString, base.gameObject); + EntityStateMachine[] components = base.gameObject.GetComponents(); + foreach (EntityStateMachine entityStateMachine in components) + { + if (entityStateMachine.customName.Contains("EyeBeam")) + { + entityStateMachine.SetNextState(new FireSpinningEyeBeam()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireDelayKnockup.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireDelayKnockup.cs new file mode 100644 index 0000000..8d09a5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireDelayKnockup.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class FireDelayKnockup : BaseState +{ + [SerializeField] + public int knockupCount; + + [SerializeField] + public float randomPositionRadius; + + public static float baseDuration; + + public static GameObject projectilePrefab; + + public static GameObject muzzleEffectPrefab; + + public static float maxDistance; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Gesture, Additive", "FireDelayKnockup", 0.1f); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "EyeballMuzzle1", transmit: false); + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "EyeballMuzzle2", transmit: false); + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "EyeballMuzzle3", transmit: false); + } + if (!NetworkServer.active) + { + return; + } + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.maxDistanceFilter = maxDistance; + bullseyeSearch.maxAngleFilter = 360f; + Ray aimRay = GetAimRay(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + List list = bullseyeSearch.GetResults().ToList(); + int num = 0; + for (int i = 0; i < knockupCount; i++) + { + if (num >= list.Count) + { + num = 0; + } + HurtBox hurtBox = list[num]; + if ((bool)hurtBox) + { + Vector2 vector = Random.insideUnitCircle * randomPositionRadius; + Vector3 vector2 = hurtBox.transform.position + new Vector3(vector.x, 0f, vector.y); + if (Physics.Raycast(new Ray(vector2 + Vector3.up * 1f, Vector3.down), out var hitInfo, 200f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + vector2 = hitInfo.point; + } + ProjectileManager.instance.FireProjectile(projectilePrefab, vector2, Quaternion.identity, base.gameObject, damageStat, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + num++; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireEyeBlast.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireEyeBlast.cs new file mode 100644 index 0000000..1a87f52 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireEyeBlast.cs @@ -0,0 +1,114 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class FireEyeBlast : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + public static GameObject muzzleflashEffectPrefab; + + [SerializeField] + public int projectileCount = 3; + + [SerializeField] + public float totalYawSpread = 5f; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float baseFireDuration = 0.2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float projectileSpeed; + + public static float force = 20f; + + public static float selfForce; + + public static string attackString; + + public static string muzzleString; + + private float duration; + + private float fireDuration; + + private int projectilesFired; + + private bool projectileSpreadIsYaw; + + private static int FireEyeBlastStateHash = Animator.StringToHash("FireEyeBlast"); + + private static int FireEyeBlastParamHash = Animator.StringToHash("FireEyeBlast.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + fireDuration = baseFireDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", FireEyeBlastStateHash, FireEyeBlastParamHash, duration); + Util.PlaySound(attackString, base.gameObject); + if (base.isAuthority) + { + base.healthComponent.TakeDamageForce(GetAimRay().direction * selfForce); + } + if (Random.value <= 0.5f) + { + projectileSpreadIsYaw = true; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + int num = Mathf.FloorToInt(base.fixedAge / fireDuration * (float)projectileCount); + if (projectilesFired <= num && projectilesFired < projectileCount) + { + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + Ray aimRay = GetAimRay(); + float speedOverride = projectileSpeed; + int num2 = Mathf.FloorToInt((float)projectilesFired - (float)(projectileCount - 1) / 2f); + float bonusYaw = 0f; + float bonusPitch = 0f; + if (projectileSpreadIsYaw) + { + bonusYaw = (float)num2 / (float)(projectileCount - 1) * totalYawSpread; + } + else + { + bonusPitch = (float)num2 / (float)(projectileCount - 1) * totalYawSpread; + } + Vector3 forward = Util.ApplySpread(aimRay.direction, 0f, 0f, 1f, 1f, bonusYaw, bonusPitch); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, speedOverride); + projectilesFired++; + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSpinningEyeBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSpinningEyeBeam.cs new file mode 100644 index 0000000..1ea3c61 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSpinningEyeBeam.cs @@ -0,0 +1,33 @@ +using EntityStates.RoboBallMini.Weapon; +using UnityEngine; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class FireSpinningEyeBeam : FireEyeBeam +{ + private Transform eyeBeamOriginTransform; + + public override void OnEnter() + { + string customName = outer.customName; + eyeBeamOriginTransform = FindModelChild(customName); + muzzleString = customName; + base.OnEnter(); + } + + public override Ray GetLaserRay() + { + Ray result = default(Ray); + if ((bool)eyeBeamOriginTransform) + { + result.origin = eyeBeamOriginTransform.position; + result.direction = eyeBeamOriginTransform.forward; + } + return result; + } + + public override bool ShouldFireLaser() + { + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSuperDelayKnockup.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSuperDelayKnockup.cs new file mode 100644 index 0000000..1675fc0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSuperDelayKnockup.cs @@ -0,0 +1,18 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.RoboBallBoss.Weapon; + +public class FireSuperDelayKnockup : FireDelayKnockup +{ + public static float shieldDuration; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + base.characterBody.AddTimedBuff(RoR2Content.Buffs.EngiShield, shieldDuration); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSuperEyeblast.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSuperEyeblast.cs new file mode 100644 index 0000000..05b3e08 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss.Weapon/FireSuperEyeblast.cs @@ -0,0 +1,5 @@ +namespace EntityStates.RoboBallBoss.Weapon; + +public class FireSuperEyeblast : FireEyeBlast +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss/DeathState.cs new file mode 100644 index 0000000..52eaa16 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss/DeathState.cs @@ -0,0 +1,85 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.RoboBallBoss; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialEffect; + + public static GameObject deathEffect; + + public static float duration = 2f; + + private float stopwatch; + + private Transform modelBaseTransform; + + private Transform centerTransform; + + private bool attemptedDeathBehavior; + + public override void OnEnter() + { + base.OnEnter(); + if (!base.modelLocator) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + centerTransform = component.FindChild("Center"); + if ((bool)initialEffect) + { + GameObject obj = Object.Instantiate(initialEffect, centerTransform.position, centerTransform.rotation); + obj.GetComponent().newDuration = duration; + obj.transform.parent = centerTransform; + } + } + modelBaseTransform = base.modelLocator.modelBaseTransform; + } + + private void AttemptDeathBehavior() + { + if (!attemptedDeathBehavior) + { + attemptedDeathBehavior = true; + if ((bool)deathEffect && NetworkServer.active && (bool)centerTransform) + { + EffectManager.SpawnEffect(deathEffect, new EffectData + { + origin = centerTransform.position + }, transmit: true); + } + if ((bool)modelBaseTransform) + { + EntityState.Destroy(modelBaseTransform.gameObject); + modelBaseTransform = null; + } + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } + } + + public override void FixedUpdate() + { + stopwatch += GetDeltaTime(); + if (stopwatch >= duration) + { + AttemptDeathBehavior(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + AttemptDeathBehavior(); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss/SpawnState.cs new file mode 100644 index 0000000..b234c0b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallBoss/SpawnState.cs @@ -0,0 +1,24 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.RoboBallBoss; + +public class SpawnState : GenericCharacterSpawnState +{ + public static GameObject spawnEffectPrefab; + + public static float spawnEffectRadius; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)spawnEffectPrefab) + { + EffectManager.SpawnEffect(spawnEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition, + scale = spawnEffectRadius + }, transmit: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallMini.Weapon/FireEyeBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallMini.Weapon/FireEyeBeam.cs new file mode 100644 index 0000000..2f191a4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallMini.Weapon/FireEyeBeam.cs @@ -0,0 +1,11 @@ +using EntityStates.EngiTurret.EngiTurretWeapon; +using RoR2; + +namespace EntityStates.RoboBallMini.Weapon; + +public class FireEyeBeam : FireBeam +{ + public override void ModifyBullet(BulletAttack bulletAttack) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboBallMini/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboBallMini/DeathState.cs new file mode 100644 index 0000000..84c70b0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboBallMini/DeathState.cs @@ -0,0 +1,11 @@ +using EntityStates.Drone; +using UnityEngine; + +namespace EntityStates.RoboBallMini; + +public class DeathState : EntityStates.Drone.DeathState +{ + public override void OnImpactServer(Vector3 contactPoint) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.RoboCratePod/Descent.cs b/ilspy_dump/ror2_csproj/EntityStates.RoboCratePod/Descent.cs new file mode 100644 index 0000000..93d1bba --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.RoboCratePod/Descent.cs @@ -0,0 +1,31 @@ +using EntityStates.SurvivorPod; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.RoboCratePod; + +public class Descent : EntityStates.SurvivorPod.Descent +{ + public static GameObject effectPrefab; + + protected override void TransitionIntoNextState() + { + base.TransitionIntoNextState(); + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, "Base", transmit: true); + } + + public override void OnExit() + { + VehicleSeat component = GetComponent(); + if ((bool)component) + { + component.EjectPassenger(); + } + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavBackpack/Opening.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavBackpack/Opening.cs new file mode 100644 index 0000000..1a2082c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavBackpack/Opening.cs @@ -0,0 +1,55 @@ +using EntityStates.Barrel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ScavBackpack; + +public class Opening : EntityState +{ + public static float duration = 1f; + + public static int maxItemDropCount; + + private ChestBehavior chestBehavior; + + private float itemDropCount; + + private float timeBetweenDrops; + + private float itemDropAge; + + private static int OpeningStateHash = Animator.StringToHash("Opening"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", OpeningStateHash); + timeBetweenDrops = duration / (float)maxItemDropCount; + chestBehavior = GetComponent(); + if ((bool)base.sfxLocator) + { + Util.PlaySound(base.sfxLocator.openSound, base.gameObject); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + itemDropAge += GetDeltaTime(); + if (itemDropCount < (float)maxItemDropCount && itemDropAge > timeBetweenDrops) + { + itemDropCount += 1f; + itemDropAge -= timeBetweenDrops; + chestBehavior.RollItem(); + chestBehavior.ItemDrop(); + } + if (base.fixedAge >= duration) + { + outer.SetNextState(new Opened()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/BaseSitState.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/BaseSitState.cs new file mode 100644 index 0000000..b0f8902 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/BaseSitState.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.ScavMonster; + +public class BaseSitState : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.AddBuff(RoR2Content.Buffs.ArmorBoost); + } + } + + public override void OnExit() + { + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.ArmorBoost); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/Death.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/Death.cs new file mode 100644 index 0000000..45ea678 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/Death.cs @@ -0,0 +1,79 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ScavMonster; + +public class Death : GenericCharacterDeath +{ + [SerializeField] + public SpawnCard spawnCard; + + public static float duration; + + private bool shouldDropPack; + + protected override bool shouldAutoDestroy => false; + + public override void OnEnter() + { + base.OnEnter(); + if (!NetworkServer.active) + { + return; + } + CharacterMaster characterMaster = (base.characterBody ? base.characterBody.master : null); + if ((bool)characterMaster) + { + bool flag = characterMaster.IsExtraLifePendingServer(); + bool flag2 = characterMaster.inventory.GetItemCount(RoR2Content.Items.Ghost) > 0; + bool flag3 = !Stage.instance || Stage.instance.scavPackDroppedServer; + shouldDropPack = !flag && !flag2 && !flag3; + if (shouldDropPack) + { + Stage.instance.scavPackDroppedServer = true; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } + + protected override void OnPreDestroyBodyServer() + { + base.OnPreDestroyBodyServer(); + if (shouldDropPack) + { + AttemptDropPack(); + } + } + + private void AttemptDropPack() + { + DirectorCore instance = DirectorCore.instance; + if ((bool)instance) + { + Xoroshiro128Plus rng = new Xoroshiro128Plus(Run.instance.stageRng.nextUint); + DirectorPlacementRule placementRule = new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.NearestNode, + position = base.characterBody.footPosition, + minDistance = 0f, + maxDistance = float.PositiveInfinity + }; + _ = (bool)instance.TrySpawnObject(new DirectorSpawnRequest(spawnCard, placementRule, rng)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/DeathLunar.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/DeathLunar.cs new file mode 100644 index 0000000..01f3139 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/DeathLunar.cs @@ -0,0 +1,5 @@ +namespace EntityStates.ScavMonster; + +public class DeathLunar : Death +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/EnergyCannonState.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/EnergyCannonState.cs new file mode 100644 index 0000000..cc0373f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/EnergyCannonState.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class EnergyCannonState : BaseState +{ + public static string muzzleName; + + protected Transform muzzleTransform; + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/EnterSit.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/EnterSit.cs new file mode 100644 index 0000000..7df4b78 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/EnterSit.cs @@ -0,0 +1,31 @@ +using RoR2; + +namespace EntityStates.ScavMonster; + +public class EnterSit : BaseSitState +{ + public static float baseDuration; + + public static string soundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(soundString, base.gameObject); + PlayCrossfade("Body", "EnterSit", "Sit.playbackRate", duration, 0.1f); + base.modelLocator.normalizeToFloor = true; + base.modelLocator.modelTransform.GetComponent().enabled = true; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new FindItem()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/ExitSit.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/ExitSit.cs new file mode 100644 index 0000000..69fb7fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/ExitSit.cs @@ -0,0 +1,30 @@ +using RoR2; + +namespace EntityStates.ScavMonster; + +public class ExitSit : BaseSitState +{ + public static float baseDuration; + + public static string soundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(soundString, base.gameObject); + PlayCrossfade("Body", "ExitSit", "Sit.playbackRate", duration, 0.1f); + base.modelLocator.normalizeToFloor = false; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/FindItem.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/FindItem.cs new file mode 100644 index 0000000..1d28c5b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/FindItem.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ScavMonster; + +public class FindItem : BaseState +{ + public static float baseDuration; + + public static float tier1Chance; + + public static int tier1Count; + + public static float tier2Chance; + + public static int tier2Count; + + public static float tier3Chance; + + public static int tier3Count; + + public static string sound; + + private float duration; + + private PickupIndex dropPickup; + + private int itemsToGrant; + + private PickupDisplay pickupDisplay; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "SitRummage", "Sit.playbackRate", duration, 0.1f); + Util.PlaySound(sound, base.gameObject); + if (base.isAuthority) + { + WeightedSelection> weightedSelection = new WeightedSelection>(); + weightedSelection.AddChoice(Run.instance.availableTier1DropList.Where(PickupIsNonBlacklistedItem).ToList(), tier1Chance); + weightedSelection.AddChoice(Run.instance.availableTier2DropList.Where(PickupIsNonBlacklistedItem).ToList(), tier2Chance); + weightedSelection.AddChoice(Run.instance.availableTier3DropList.Where(PickupIsNonBlacklistedItem).ToList(), tier3Chance); + List list = weightedSelection.Evaluate(Random.value); + dropPickup = list[Random.Range(0, list.Count)]; + PickupDef pickupDef = PickupCatalog.GetPickupDef(dropPickup); + if (pickupDef != null) + { + ItemDef itemDef = ItemCatalog.GetItemDef(pickupDef.itemIndex); + if (itemDef != null) + { + itemsToGrant = 0; + switch (itemDef.tier) + { + case ItemTier.Tier1: + itemsToGrant = tier1Count; + break; + case ItemTier.Tier2: + itemsToGrant = tier2Count; + break; + case ItemTier.Tier3: + itemsToGrant = tier3Count; + break; + default: + itemsToGrant = 1; + break; + } + } + } + } + Transform transform = FindModelChild("PickupDisplay"); + pickupDisplay = transform.GetComponent(); + pickupDisplay.SetPickupIndex(dropPickup); + } + + public override void OnExit() + { + pickupDisplay.SetPickupIndex(PickupIndex.none); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new GrantItem + { + dropPickup = dropPickup, + itemsToGrant = itemsToGrant + }); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(dropPickup); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dropPickup = reader.ReadPickupIndex(); + } + + private bool PickupIsNonBlacklistedItem(PickupIndex pickupIndex) + { + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + if (pickupDef == null) + { + return false; + } + ItemDef itemDef = ItemCatalog.GetItemDef(pickupDef.itemIndex); + if (itemDef == null) + { + return false; + } + return itemDef.DoesNotContainTag(ItemTag.AIBlacklist); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/FireEnergyCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/FireEnergyCannon.cs new file mode 100644 index 0000000..bd69a35 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/FireEnergyCannon.cs @@ -0,0 +1,82 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class FireEnergyCannon : EnergyCannonState +{ + public static float baseDuration; + + public static float baseRefireDuration; + + public static string sound; + + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static float recoilAmplitude = 1f; + + public static float projectilePitchBonus; + + public static float projectileYawBonusPerRefire; + + public static int projectileCount; + + public static int maxRefireCount; + + public int currentRefire; + + private float duration; + + private float refireDuration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + refireDuration = baseRefireDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(sound, base.gameObject, attackSpeedStat); + PlayCrossfade("Body", "FireEnergyCannon", "FireEnergyCannon.playbackRate", duration, 0.1f); + AddRecoil(-2f * recoilAmplitude, -3f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, EnergyCannonState.muzzleName, transmit: false); + } + if (base.isAuthority) + { + float num = ((currentRefire % 2 == 0) ? 1 : (-1)); + float num2 = Mathf.Ceil((float)currentRefire / 2f) * projectileYawBonusPerRefire; + for (int i = 0; i < projectileCount; i++) + { + Ray aimRay = GetAimRay(); + aimRay.direction = Util.ApplySpread(aimRay.direction, minSpread, maxSpread, 1f, 1f, num * num2, projectilePitchBonus); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= refireDuration && currentRefire + 1 < maxRefireCount && base.isAuthority) + { + FireEnergyCannon fireEnergyCannon = new FireEnergyCannon(); + fireEnergyCannon.currentRefire = currentRefire + 1; + outer.SetNextState(fireEnergyCannon); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/GrantItem.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/GrantItem.cs new file mode 100644 index 0000000..25ff531 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/GrantItem.cs @@ -0,0 +1,59 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.ScavMonster; + +public class GrantItem : BaseState +{ + public PickupIndex dropPickup; + + public int itemsToGrant; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + GrantPickupServer(dropPickup, itemsToGrant); + } + if (base.isAuthority) + { + outer.SetNextState(new ExitSit()); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(dropPickup); + writer.WritePackedUInt32((uint)itemsToGrant); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + dropPickup = reader.ReadPickupIndex(); + itemsToGrant = (int)reader.ReadPackedUInt32(); + } + + private void GrantPickupServer(PickupIndex pickupIndex, int countToGrant) + { + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + if (pickupDef != null) + { + ItemIndex itemIndex = pickupDef.itemIndex; + if (!(ItemCatalog.GetItemDef(itemIndex) == null)) + { + base.characterBody.inventory.GiveItem(itemIndex, countToGrant); + Chat.SendBroadcastChat(new Chat.PlayerPickupChatMessage + { + subjectAsCharacterBody = base.characterBody, + baseToken = "MONSTER_PICKUP", + pickupToken = pickupDef.nameToken, + pickupColor = pickupDef.baseColor, + pickupQuantity = (uint)itemsToGrant + }); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/PrepEnergyCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/PrepEnergyCannon.cs new file mode 100644 index 0000000..b827207 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/PrepEnergyCannon.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class PrepEnergyCannon : EnergyCannonState +{ + public static float baseDuration; + + public static string sound; + + public static GameObject chargeEffectPrefab; + + private GameObject chargeInstance; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "PrepEnergyCannon", "PrepEnergyCannon.playbackRate", duration, 0.1f); + Util.PlaySound(sound, base.gameObject); + if ((bool)muzzleTransform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + chargeInstance.transform.parent = muzzleTransform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + StartAimMode(0.5f); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new FireEnergyCannon()); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/PrepSack.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/PrepSack.cs new file mode 100644 index 0000000..49a9920 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/PrepSack.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class PrepSack : SackBaseState +{ + public static float baseDuration; + + public static string sound; + + public static GameObject chargeEffectPrefab; + + private GameObject chargeInstance; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "PrepSack", "PrepSack.playbackRate", duration, 0.1f); + Util.PlaySound(sound, base.gameObject); + StartAimMode(duration); + if ((bool)muzzleTransform && (bool)chargeEffectPrefab) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + chargeInstance.transform.parent = muzzleTransform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new ThrowSack()); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/SackBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/SackBaseState.cs new file mode 100644 index 0000000..898f65d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/SackBaseState.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class SackBaseState : BaseState +{ + public static string muzzleName; + + protected Transform muzzleTransform; + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/Sit.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/Sit.cs new file mode 100644 index 0000000..d468100 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/Sit.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class Sit : BaseSitState +{ + public static string soundString; + + public static float minimumDuration; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "SitLoop", 0.1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.inputBank.moveVector.sqrMagnitude >= Mathf.Epsilon && base.fixedAge >= minimumDuration) + { + outer.SetNextState(new ExitSit()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/ThrowSack.cs b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/ThrowSack.cs new file mode 100644 index 0000000..08d5123 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ScavMonster/ThrowSack.cs @@ -0,0 +1,98 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.ScavMonster; + +public class ThrowSack : SackBaseState +{ + public static float baseDuration; + + public static string sound; + + public static GameObject effectPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static string attackSoundString; + + public static float projectileVelocity; + + public static float minimumDistance; + + public static float timeToTarget = 3f; + + public static int projectileCount; + + private float duration; + + private static int ThrowSackStateHash = Animator.StringToHash("ThrowSack"); + + private static int ThrowSackParamHash = Animator.StringToHash("ThrowSack.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(sound, base.gameObject, attackSpeedStat); + PlayAnimation("Body", ThrowSackStateHash, ThrowSackParamHash, duration); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, SackBaseState.muzzleName, transmit: false); + } + Fire(); + } + + private void Fire() + { + Ray aimRay = GetAimRay(); + Ray ray = aimRay; + Ray ray2 = aimRay; + Vector3 point = aimRay.GetPoint(minimumDistance); + bool flag = false; + if (Util.CharacterRaycast(base.gameObject, ray, out var hitInfo, 500f, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + point = hitInfo.point; + flag = true; + } + float magnitude = projectileVelocity; + if (flag) + { + Vector3 vector = point - ray2.origin; + Vector2 vector2 = new Vector2(vector.x, vector.z); + float magnitude2 = vector2.magnitude; + Vector2 vector3 = vector2 / magnitude2; + if (magnitude2 < minimumDistance) + { + magnitude2 = minimumDistance; + } + float y = Trajectory.CalculateInitialYSpeed(timeToTarget, vector.y); + float num = magnitude2 / timeToTarget; + Vector3 direction = new Vector3(vector3.x * num, y, vector3.y * num); + magnitude = direction.magnitude; + ray2.direction = direction; + } + for (int i = 0; i < projectileCount; i++) + { + Quaternion rotation = Util.QuaternionSafeLookRotation(Util.ApplySpread(ray2.direction, minSpread, maxSpread, 1f, 1f)); + ProjectileManager.instance.FireProjectile(projectilePrefab, ray2.origin, rotation, base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, magnitude); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scorchling/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/DeathState.cs new file mode 100644 index 0000000..089687a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/DeathState.cs @@ -0,0 +1,79 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Scorchling; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathExplosion; + + public static string deathSoundString; + + public static string stopBurrowLoopString; + + public static float animDuration = 1f; + + public static float cleanUpDuration = 0.3f; + + public static float printDuration; + + private bool burrowed; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayAnimation("FullBody, Override", "Burrow", "Burrow.playbackRate", animDuration); + } + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + PrintController printController = modelTransform.gameObject.AddComponent(); + printController.printTime = printDuration; + printController.enabled = true; + printController.startingPrintHeight = 99999f; + printController.maxPrintHeight = 99999f; + printController.startingPrintBias = 1f; + printController.maxPrintBias = 3.5f; + printController.animateFlowmapPower = true; + printController.startingFlowmapPower = 1.14f; + printController.maxFlowmapPower = 30f; + printController.disableWhenFinished = false; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + } + cleanUpDuration += animDuration; + Util.PlaySound(deathSoundString, base.gameObject); + Util.PlaySound(stopBurrowLoopString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!burrowed && base.fixedAge >= animDuration) + { + EffectManager.SpawnEffect(deathExplosion, new EffectData + { + origin = base.characterBody.corePosition, + scale = 4f + }, transmit: true); + burrowed = true; + } + if (base.fixedAge >= cleanUpDuration) + { + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingBreach.cs b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingBreach.cs new file mode 100644 index 0000000..b92f4c0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingBreach.cs @@ -0,0 +1,202 @@ +using RoR2; +using RoR2.CharacterAI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Scorchling; + +public class ScorchlingBreach : BaseState +{ + [SerializeField] + [Header("Timing")] + public float crackToBreachTime = 1f; + + [SerializeField] + public float breachToBurrow = 5f; + + [SerializeField] + public float burrowToEndOfTime = 1f; + + [SerializeField] + public float animDuration = 1f; + + [Header("Explosion Attr")] + [SerializeField] + public float blastProcCoefficient; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastForce; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public float knockbackForce; + + [Header("FX Objects")] + [SerializeField] + public GameObject crackEffectPrefab; + + [SerializeField] + public float crackRadius = 1f; + + [SerializeField] + public GameObject blastEffectPrefab; + + [SerializeField] + public GameObject blastImpactEffectPrefab; + + [SerializeField] + public float blastRadius = 1f; + + [SerializeField] + public GameObject burrowEffectPrefab; + + [SerializeField] + public float burrowRadius = 1f; + + [Header("Sound Strings")] + [SerializeField] + public string preBreachSoundString; + + [SerializeField] + public string breachSoundString; + + [SerializeField] + public string burrowSoundString; + + [SerializeField] + public string burrowLoopSoundString; + + [SerializeField] + public string burrowStopLoopSoundString; + + public bool proceedImmediatelyToLavaBomb; + + private bool breached; + + private bool burrowed; + + private bool amServer; + + private Vector3 breachPosition; + + private ScorchlingController scorchlingController; + + private CharacterBody enemyCBody; + + public override void OnEnter() + { + base.OnEnter(); + amServer = NetworkServer.active; + scorchlingController = base.characterBody.GetComponent(); + Util.PlaySound(preBreachSoundString, base.gameObject); + if (amServer) + { + enemyCBody = base.characterBody.master.GetComponent().currentEnemy?.characterBody; + if (proceedImmediatelyToLavaBomb) + { + breachToBurrow = 1f; + } + breachToBurrow += crackToBreachTime; + burrowToEndOfTime += breachToBurrow; + breachPosition = base.characterBody.footPosition; + if (!proceedImmediatelyToLavaBomb && (bool)enemyCBody) + { + breachPosition = enemyCBody.footPosition; + } + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 0f; + } + base.characterBody.SetAimTimer(breachToBurrow); + TeleportHelper.TeleportBody(base.characterBody, breachPosition); + EffectManager.SpawnEffect(crackEffectPrefab, new EffectData + { + origin = breachPosition, + scale = crackRadius + }, transmit: true); + scorchlingController.SetTeleportPermission(b: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (amServer && base.fixedAge < crackToBreachTime && enemyCBody != null) + { + Vector3 normalized = (enemyCBody.corePosition - base.characterBody.corePosition).normalized; + base.characterBody.characterDirection.forward = normalized; + } + if (!breached && base.fixedAge > crackToBreachTime) + { + breached = true; + scorchlingController.Breach(); + PlayAnimation("FullBody, Override", "Breach", "Breach.playbackRate", animDuration); + Util.PlaySound(breachSoundString, base.gameObject); + Util.PlaySound(burrowStopLoopSoundString, base.gameObject); + if (amServer) + { + DetonateAuthority(); + } + } + if (base.fixedAge > burrowToEndOfTime) + { + DoExit(); + } + } + + private void DoExit() + { + if (proceedImmediatelyToLavaBomb) + { + outer.SetNextState(new ScorchlingLavaBomb()); + } + else + { + outer.SetNextStateToMain(); + } + } + + protected BlastAttack.Result DetonateAuthority() + { + EffectManager.SpawnEffect(blastEffectPrefab, new EffectData + { + origin = breachPosition, + scale = blastRadius + }, transmit: true); + return new BlastAttack + { + attacker = base.gameObject, + baseDamage = damageStat * blastDamageCoefficient, + baseForce = blastForce, + bonusForce = blastBonusForce, + crit = RollCrit(), + damageType = DamageType.Stun1s, + falloffModel = BlastAttack.FalloffModel.None, + procCoefficient = blastProcCoefficient, + radius = blastRadius, + position = breachPosition, + attackerFiltering = AttackerFiltering.NeverHitSelf, + impactEffect = EffectCatalog.FindEffectIndexFromPrefab(blastImpactEffectPrefab), + teamIndex = base.teamComponent.teamIndex + }.Fire(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (proceedImmediatelyToLavaBomb) + { + return InterruptPriority.Frozen; + } + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingEnsureBurrow.cs b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingEnsureBurrow.cs new file mode 100644 index 0000000..0a8c0af --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingEnsureBurrow.cs @@ -0,0 +1,92 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Scorchling; + +public class ScorchlingEnsureBurrow : BaseState +{ + [SerializeField] + public string burrowSoundString; + + [SerializeField] + public string burrowLoopSoundString; + + [SerializeField] + public string burrowStopLoopSoundString; + + [SerializeField] + public GameObject burrowEffectPrefab; + + [SerializeField] + public float burrowRadius = 1f; + + [SerializeField] + public float animDurationBurrow = 1f; + + [SerializeField] + public float burrowAnimationDuration = 1f; + + private ScorchlingController sController; + + private bool waitingForBurrow; + + public override void OnEnter() + { + base.OnEnter(); + sController = base.characterBody.GetComponent(); + if (!sController.isBurrowed) + { + Util.PlaySound(burrowSoundString, base.gameObject); + Util.PlaySound(burrowLoopSoundString, base.gameObject); + EffectManager.SpawnEffect(burrowEffectPrefab, new EffectData + { + origin = base.characterBody.footPosition, + scale = burrowRadius + }, transmit: true); + PlayAnimation("FullBody, Override", "Burrow", "Burrow.playbackRate", animDurationBurrow); + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 0f; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + waitingForBurrow = true; + } + } + + public override void Update() + { + base.Update(); + HandleWaitForBurrow(); + } + + public override void OnExit() + { + base.OnExit(); + HandleWaitForBurrow(); + } + + private void HandleWaitForBurrow() + { + if (waitingForBurrow && base.age > burrowAnimationDuration) + { + sController.Burrow(); + waitingForBurrow = false; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (waitingForBurrow) + { + return InterruptPriority.Frozen; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingLavaBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingLavaBomb.cs new file mode 100644 index 0000000..a97e417 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/ScorchlingLavaBomb.cs @@ -0,0 +1,201 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Scorchling; + +public class ScorchlingLavaBomb : BaseState +{ + [SerializeField] + [Header("Timing")] + public float breachToSpitTime = 1f; + + [SerializeField] + public float spitToLaunchTime = 0.3f; + + [SerializeField] + public float spitToBurrowTime = 5f; + + [SerializeField] + public float burrowToEndOfTime = 1f; + + [SerializeField] + public float animDurationBreach = 1f; + + [SerializeField] + public float animDurationSpit = 1f; + + [SerializeField] + public float animDurationBurrow = 1f; + + [SerializeField] + public float animDurationPostSpit = 0.75f; + + [SerializeField] + public float percentageToFireProjectile = 0.75f; + + [SerializeField] + [Header("FX Objects")] + public GameObject burrowEffectPrefab; + + [SerializeField] + public float burrowRadius = 1f; + + [Header("Sound Strings")] + [SerializeField] + public string breachSoundString; + + [SerializeField] + public string spitSoundString; + + [SerializeField] + public string burrowSoundString; + + [SerializeField] + public string burrowLoopSoundString; + + [SerializeField] + public string burrowStopLoopSoundString; + + [Header("Lava Bomb Projectile")] + public static GameObject mortarProjectilePrefab; + + public static GameObject mortarMuzzleflashEffect; + + public static int mortarCount; + + public static string mortarMuzzleName; + + public static string mortarSoundString; + + public static float mortarDamageCoefficient; + + public static float timeToTarget = 3f; + + public static float projectileVelocity = 55f; + + public static float minimumDistance; + + private bool spitStarted; + + private bool firedProjectile; + + private bool earlyExit; + + private ScorchlingController sController; + + public override void OnEnter() + { + base.OnEnter(); + sController = base.characterBody.GetComponent(); + animDurationBreach = (sController.isBurrowed ? animDurationBreach : 0f); + spitToBurrowTime += animDurationBreach + animDurationSpit; + burrowToEndOfTime += spitToBurrowTime; + if (sController.isBurrowed) + { + earlyExit = true; + if (Util.HasEffectiveAuthority(base.characterBody.networkIdentity)) + { + outer.SetNextState(new ScorchlingBreach + { + proceedImmediatelyToLavaBomb = true, + breachToBurrow = breachToSpitTime + }); + } + } + else + { + base.characterBody.SetAimTimer(burrowToEndOfTime); + } + } + + public override void FixedUpdate() + { + if (earlyExit) + { + return; + } + base.FixedUpdate(); + if (!spitStarted && base.fixedAge > animDurationBreach) + { + spitStarted = true; + PlayAnimation("FullBody, Override", "Spit", "Spit.playbackRate", animDurationSpit); + } + if (spitStarted && !firedProjectile && base.fixedAge > animDurationSpit * percentageToFireProjectile + animDurationBreach) + { + firedProjectile = true; + Util.PlaySound(spitSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(mortarMuzzleflashEffect, base.gameObject, mortarMuzzleName, transmit: false); + if (base.isAuthority) + { + Spit(); + } + } + if (firedProjectile && base.fixedAge > animDurationBreach + animDurationSpit + animDurationPostSpit) + { + outer.SetNextStateToMain(); + } + } + + public void Spit() + { + Transform transform = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild("MuzzleFire"); + Ray ray = new Ray(transform.position, transform.forward); + Ray ray2 = new Ray(ray.origin, Vector3.up); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = ray.origin; + bullseyeSearch.searchDirection = ray.direction; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + bool flag = false; + Vector3 vector = Vector3.zero; + RaycastHit hitInfo; + if ((bool)hurtBox) + { + vector = hurtBox.transform.position; + flag = true; + } + else if (Physics.Raycast(ray, out hitInfo, 1000f, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) + { + vector = hitInfo.point; + flag = true; + } + float magnitude = projectileVelocity; + if (flag) + { + Vector3 vector2 = vector - ray2.origin; + Vector2 vector3 = new Vector2(vector2.x, vector2.z); + float magnitude2 = vector3.magnitude; + Vector2 vector4 = vector3 / magnitude2; + if (magnitude2 < minimumDistance) + { + magnitude2 = minimumDistance; + } + float y = Trajectory.CalculateInitialYSpeed(timeToTarget, vector2.y); + float num = magnitude2 / timeToTarget; + Vector3 direction = new Vector3(vector4.x * num, y, vector4.y * num); + magnitude = direction.magnitude; + ray2.direction = direction; + } + Quaternion rotation = Util.QuaternionSafeLookRotation(ray2.direction); + ProjectileManager.instance.FireProjectile(mortarProjectilePrefab, ray2.origin, rotation, base.gameObject, damageStat * mortarDamageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, magnitude); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scorchling/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/SpawnState.cs new file mode 100644 index 0000000..d04a015 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scorchling/SpawnState.cs @@ -0,0 +1,33 @@ +using RoR2; + +namespace EntityStates.Scorchling; + +public class SpawnState : EntityState +{ + public static float duration = 0.5f; + + public static string spawnSoundString; + + public static string burrowLoopSoundString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + Util.PlaySound(burrowLoopSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scrapper/Idle.cs b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/Idle.cs new file mode 100644 index 0000000..30442fd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/Idle.cs @@ -0,0 +1,6 @@ +namespace EntityStates.Scrapper; + +public class Idle : ScrapperBaseState +{ + protected override bool enableInteraction => true; +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scrapper/ScrapperBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/ScrapperBaseState.cs new file mode 100644 index 0000000..b8f5193 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/ScrapperBaseState.cs @@ -0,0 +1,20 @@ +using RoR2; + +namespace EntityStates.Scrapper; + +public class ScrapperBaseState : BaseState +{ + protected PickupPickerController pickupPickerController; + + protected ScrapperController scrapperController; + + protected virtual bool enableInteraction => true; + + public override void OnEnter() + { + base.OnEnter(); + pickupPickerController = GetComponent(); + scrapperController = GetComponent(); + pickupPickerController.SetAvailable(enableInteraction); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scrapper/Scrapping.cs b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/Scrapping.cs new file mode 100644 index 0000000..a39473e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/Scrapping.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Scrapper; + +public class Scrapping : ScrapperBaseState +{ + public static string enterSoundString; + + public static string exitSoundString; + + public static float duration; + + private static int ScrappingStateHash = Animator.StringToHash("Scrapping"); + + private static int ScrappingParamHash = Animator.StringToHash("Scrapping.playbackRate"); + + protected override bool enableInteraction => false; + + public override void OnEnter() + { + base.OnEnter(); + FindModelChild("ScrappingEffect").gameObject.SetActive(value: true); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Base", ScrappingStateHash, ScrappingParamHash, duration); + } + + public override void OnExit() + { + FindModelChild("ScrappingEffect").gameObject.SetActive(value: false); + Util.PlaySound(exitSoundString, base.gameObject); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new ScrappingToIdle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scrapper/ScrappingToIdle.cs b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/ScrappingToIdle.cs new file mode 100644 index 0000000..c069aab --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/ScrappingToIdle.cs @@ -0,0 +1,73 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Scrapper; + +public class ScrappingToIdle : ScrapperBaseState +{ + public static string enterSoundString; + + public static string exitSoundString; + + public static float duration; + + public static float dropUpVelocityStrength; + + public static float dropForwardVelocityStrength; + + public static GameObject muzzleflashEffectPrefab; + + public static string muzzleString; + + private bool foundValidScrap; + + private static int ScrappingToIdleStateHash = Animator.StringToHash("ScrappingToIdle"); + + private static int ScrappingParamHash = Animator.StringToHash("Scrapping.playbackRate"); + + protected override bool enableInteraction => false; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Base", ScrappingToIdleStateHash, ScrappingParamHash, duration); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (NetworkServer.active) + { + foundValidScrap = false; + PickupIndex none = PickupIndex.none; + none = PickupCatalog.FindScrapIndexForItemTier(ItemCatalog.GetItemDef(scrapperController.lastScrappedItemIndex).tier); + if (none != PickupIndex.none) + { + foundValidScrap = true; + Transform transform = FindModelChild(muzzleString); + PickupDropletController.CreatePickupDroplet(none, transform.position, Vector3.up * dropUpVelocityStrength + transform.forward * dropForwardVelocityStrength); + scrapperController.itemsEaten--; + } + } + } + + public override void OnExit() + { + Util.PlaySound(exitSoundString, base.gameObject); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (foundValidScrap && scrapperController.itemsEaten > 0 && base.fixedAge > duration / 2f) + { + outer.SetNextState(new ScrappingToIdle()); + } + else if (base.fixedAge > duration) + { + outer.SetNextState(new Idle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Scrapper/WaitToBeginScrapping.cs b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/WaitToBeginScrapping.cs new file mode 100644 index 0000000..a4abf4a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Scrapper/WaitToBeginScrapping.cs @@ -0,0 +1,17 @@ +namespace EntityStates.Scrapper; + +public class WaitToBeginScrapping : ScrapperBaseState +{ + public static float duration; + + protected override bool enableInteraction => false; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new Scrapping()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseActive.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseActive.cs new file mode 100644 index 0000000..f83139a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseActive.cs @@ -0,0 +1,79 @@ +using RoR2; +using RoR2.Audio; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class BaseActive : BaseScopeState +{ + [SerializeField] + public SkillDef primaryOverride; + + [SerializeField] + public LoopSoundDef loopSound; + + private GenericSkill overriddenSkill; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + public override void OnEnter() + { + base.OnEnter(); + SetScopeAlpha(1f); + StartScopeParamsOverride(0f); + GenericSkill genericSkill = base.skillLocator?.primary; + if ((bool)genericSkill) + { + TryOverrideSkill(genericSkill); + genericSkill.onSkillChanged += TryOverrideSkill; + } + if (base.isAuthority) + { + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSound); + } + } + + public override void OnExit() + { + if (loopPtr.isValid) + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + } + GenericSkill genericSkill = base.skillLocator?.primary; + if ((bool)genericSkill) + { + genericSkill.onSkillChanged -= TryOverrideSkill; + } + if ((bool)overriddenSkill) + { + overriddenSkill.UnsetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + } + EndScopeParamsOverride(0f); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (!IsKeyDownAuthority() || base.characterBody.isSprinting)) + { + outer.SetNextState(GetNextState()); + } + } + + private void TryOverrideSkill(GenericSkill skill) + { + if ((bool)skill && !overriddenSkill && !skill.HasSkillOverrideOfPriority(GenericSkill.SkillOverridePriority.Contextual)) + { + overriddenSkill = skill; + overriddenSkill.SetSkillOverride(this, primaryOverride, GenericSkill.SkillOverridePriority.Contextual); + overriddenSkill.stock = base.skillLocator.secondary.stock; + } + } + + protected virtual BaseWindDown GetNextState() + { + return new BaseWindDown(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseScopeState.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseScopeState.cs new file mode 100644 index 0000000..1ccd8aa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseScopeState.cs @@ -0,0 +1,117 @@ +using RoR2; +using RoR2.HudOverlay; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class BaseScopeState : BaseSkillState +{ + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public GameObject scopeOverlayPrefab; + + [SerializeField] + public CharacterCameraParams cameraParams; + + [SerializeField] + public float cameraOverridePriority; + + public static string mecanimBoolName; + + private OverlayController overlayController; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private CameraTargetParams.CameraParamsOverrideHandle cameraParamsOverrideHandle; + + public static bool inScope; + + public override void OnEnter() + { + base.OnEnter(); + overlayController = HudOverlayManager.AddOverlay(base.gameObject, new OverlayCreationParams + { + prefab = scopeOverlayPrefab, + childLocatorEntry = "ScopeContainer" + }); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(mecanimBoolName, value: true); + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + inScope = true; + } + + public override void OnExit() + { + inScope = false; + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetBool(mecanimBoolName, value: false); + } + RemoveOverlay(0f); + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + protected void SetScopeAlpha(float alpha) + { + if (overlayController != null) + { + overlayController.alpha = alpha; + } + } + + protected void RemoveOverlay(float transitionDuration) + { + if (overlayController != null) + { + HudOverlayManager.RemoveOverlay(overlayController); + overlayController = null; + } + } + + protected void StartScopeParamsOverride(float transitionDuration) + { + if (!cameraParamsOverrideHandle.isValid) + { + cameraParamsOverrideHandle = base.cameraTargetParams.AddParamsOverride(new CameraTargetParams.CameraParamsOverrideRequest + { + cameraParamsData = cameraParams.data, + priority = cameraOverridePriority + }, transitionDuration); + } + } + + protected void EndScopeParamsOverride(float transitionDuration) + { + if (cameraParamsOverrideHandle.isValid) + { + base.cameraTargetParams.RemoveParamsOverride(cameraParamsOverrideHandle, transitionDuration); + cameraParamsOverrideHandle = default(CameraTargetParams.CameraParamsOverrideHandle); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected virtual CharacterCameraParams GetCameraParams() + { + return cameraParams; + } + + protected virtual float GetScopeEntryDuration() + { + return 0f; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseWindDown.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseWindDown.cs new file mode 100644 index 0000000..57aae74 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseWindDown.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class BaseWindDown : BaseScopeState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string enterSoundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + SetScopeAlpha(1f); + RemoveOverlay(duration); + StartScopeParamsOverride(0f); + EndScopeParamsOverride(duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override void Update() + { + base.Update(); + SetScopeAlpha(1f - Mathf.Clamp01(base.age / duration)); + } + + protected override CharacterCameraParams GetCameraParams() + { + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseWindUp.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseWindUp.cs new file mode 100644 index 0000000..393516f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/BaseWindUp.cs @@ -0,0 +1,61 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class BaseWindUp : BaseScopeState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string enterSoundString; + + private float duration; + + public override void OnEnter() + { + duration = baseDuration; + base.OnEnter(); + SetScopeAlpha(0f); + StartScopeParamsOverride(duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void OnExit() + { + EndScopeParamsOverride(0f); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + BaseActive nextState = GetNextState(); + nextState.activatorSkillSlot = base.activatorSkillSlot; + outer.SetNextState(nextState); + } + } + + public override void Update() + { + base.Update(); + SetScopeAlpha(Mathf.Clamp01(base.age / duration)); + } + + protected virtual BaseActive GetNextState() + { + return new BaseActive(); + } + + protected override float GetScopeEntryDuration() + { + return duration; + } + + public override void ModifyNextState(EntityState nextState) + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/InnerStrength.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/InnerStrength.cs new file mode 100644 index 0000000..2a0dd7a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/InnerStrength.cs @@ -0,0 +1,8 @@ +namespace EntityStates.Seeker; + +public class InnerStrength : BaseState +{ + public override void OnEnter() + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/Meditate.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/Meditate.cs new file mode 100644 index 0000000..164df8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/Meditate.cs @@ -0,0 +1,22 @@ +using RoR2.HudOverlay; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class Meditate : BaseWindUp +{ + [SerializeField] + public new GameObject scopeOverlayPrefab; + + private OverlayController overlayController; + + public override void OnEnter() + { + base.OnEnter(); + overlayController = HudOverlayManager.AddOverlay(base.gameObject, new OverlayCreationParams + { + prefab = scopeOverlayPrefab, + childLocatorEntry = "ScopeContainer" + }); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/MeditationUI.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/MeditationUI.cs new file mode 100644 index 0000000..4bfb454 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/MeditationUI.cs @@ -0,0 +1,436 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.HudOverlay; +using RoR2.UI; +using UnityEngine; +using UnityEngine.UI; + +namespace EntityStates.Seeker; + +public class MeditationUI : BaseSkillState +{ + [SerializeField] + [Header("UI")] + public GameObject scopeOverlayPrefab; + + [SerializeField] + public float duration = 5f; + + [SerializeField] + public float timePenalty = 1f; + + [SerializeField] + public float failureCooldownPenalty = 5f; + + [SerializeField] + public float animDuration; + + [SerializeField] + public float smallHopVelocity; + + [SerializeField] + public Sprite primaryIcon; + + [SerializeField] + public Sprite secondaryIcon; + + [SerializeField] + public Sprite utilityIcon; + + [SerializeField] + public Sprite specialIcon; + + [SerializeField] + public SeekerController seekerController; + + [SerializeField] + public GameObject lotusPrefab; + + [SerializeField] + public float wrapUpDuration; + + [SerializeField] + public GameObject successEffectPrefab; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public string startSoundString; + + [SerializeField] + public string stopSoundString; + + [SerializeField] + public string timeoutSoundString; + + [SerializeField] + public string successSoundString; + + [SerializeField] + public string inputCorrectSoundString; + + [SerializeField] + public string inputFailSoundString; + + [SerializeField] + [Header("Healing Explosion")] + public float healingExplosionAmount = 10f; + + [SerializeField] + public float healingOverShield = 5f; + + [SerializeField] + public float blastRadius = 5f; + + [SerializeField] + public float damageCoefficient = 5f; + + [SerializeField] + public float blastForce = 5f; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public float blastProcCoefficient = 5f; + + [SerializeField] + public float percentPerGate = 0.75f; + + [SerializeField] + public float overShieldPercent = 0.25f; + + [SerializeField] + public float startingOverShieldPercentage = 0.33f; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private GameObject lotus; + + private OverlayController overlayController; + + private bool meditationSuccess; + + private ICharacterGravityParameterProvider characterGravityParameterProvider; + + private ChildLocator overlayInstanceChildLocator; + + private ChildLocator lotusChildLocator; + + private List fillUiList = new List(); + + private CameraTargetParams.AimRequest aimRequest; + + private bool spawnedLotus; + + private bool failed; + + private bool meditationWrapUp; + + private bool wrapUpAnimationPlayed; + + private float wrapUpTimer; + + private float startingYaw; + + private EntityStateMachine bodyStateMachine; + + private float explosionHealingMod; + + private bool upReady = true; + + private bool downReady = true; + + private bool rightReady = true; + + private bool leftReady = true; + + private static string[] c = new string[5] { "ArrowInput1", "ArrowInput2", "ArrowInput3", "ArrowInput4", "ArrowInput5" }; + + public override void OnEnter() + { + base.OnEnter(); + EntityStateMachine[] components = base.characterBody.gameObject.GetComponents(); + foreach (EntityStateMachine entityStateMachine in components) + { + if (entityStateMachine.customName == "Body") + { + bodyStateMachine = entityStateMachine; + } + } + bodyStateMachine.SetNextState(new Idle()); + explosionHealingMod = base.characterBody.maxHealth; + if (explosionHealingMod < base.characterBody.baseMaxHealth) + { + explosionHealingMod = base.characterBody.baseMaxHealth; + } + base.healthComponent.AddBarrierAuthority(explosionHealingMod * startingOverShieldPercentage); + seekerController = base.characterBody.transform.GetComponent(); + if (base.isAuthority) + { + seekerController.RandomizeMeditationInputs(); + } + SmallHop(base.characterMotor, smallHopVelocity); + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 0f; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + PlayAnimation("FullBody, Override", "MeditationStart", "Meditation.playbackRate", animDuration); + characterGravityParameterProvider = base.gameObject.GetComponent(); + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount++; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + overlayController = HudOverlayManager.AddOverlay(base.gameObject, new OverlayCreationParams + { + prefab = scopeOverlayPrefab, + childLocatorEntry = "CrosshairExtras" + }); + overlayController.onInstanceAdded += OnOverlayInstanceAdded; + overlayController.onInstanceRemove += OnOverlayInstanceRemoved; + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + CameraTargetParams component = base.gameObject.GetComponent(); + if ((bool)component) + { + aimRequest = component.RequestAimType(CameraTargetParams.AimType.ZoomedOut); + } + startingYaw = base.characterDirection.yaw; + Util.PlaySound(startSoundString, base.gameObject); + } + + public override void Update() + { + if (seekerController.meditationUIDirty) + { + seekerController.meditationUIDirty = false; + UpdateUIInputSequence(); + } + base.characterDirection.yaw = startingYaw; + base.characterDirection.moveVector = base.characterDirection.forward; + base.Update(); + if (meditationWrapUp) + { + wrapUpTimer += Time.deltaTime; + if (wrapUpTimer > wrapUpDuration) + { + outer.SetNextStateToMain(); + } + if (!wrapUpAnimationPlayed) + { + wrapUpAnimationPlayed = true; + if (meditationSuccess) + { + PlayAnimation("FullBody, Override", "MeditationSuccess", "Meditation.playbackRate", animDuration); + Util.PlaySound(successSoundString, base.gameObject); + lotus.GetComponentInChildren().Play("MeditationSuccess"); + EffectManager.SpawnEffect(successEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: true); + if (base.isAuthority) + { + float num = 0f; + float num2 = 0f; + seekerController.IncrementChakraGate(); + if (base.characterBody.HasBuff(DLC2Content.Buffs.ChakraBuff)) + { + num2 = base.characterBody.GetBuffCount(DLC2Content.Buffs.ChakraBuff); + num = num2 * percentPerGate; + } + seekerController.CallCmdTriggerHealPulse((healingExplosionAmount * num2 + 0.04f) * explosionHealingMod, base.characterBody.corePosition, blastRadius); + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.characterBody.gameObject; + blastAttack.baseDamage = (damageCoefficient + num) * base.characterBody.damage; + blastAttack.baseForce = blastForce; + blastAttack.bonusForce = blastBonusForce; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.crit = base.characterBody.RollCrit(); + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.inflictor = base.gameObject; + blastAttack.position = base.characterBody.corePosition; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = blastProcCoefficient; + blastAttack.radius = blastRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.teamIndex = base.teamComponent.teamIndex; + blastAttack.Fire(); + } + } + else + { + PlayAnimation("FullBody, Override", "MeditationFail", "Meditation.playbackRate", animDuration); + Util.PlaySound(timeoutSoundString, base.gameObject); + lotus.GetComponentInChildren().Play("MeditationFail"); + outer.SetNextStateToMain(); + } + } + } + int num3 = -1; + if (base.inputBank.rawMoveUp.justPressed) + { + num3 = 0; + } + if (base.inputBank.rawMoveDown.justPressed) + { + num3 = 1; + } + if (base.inputBank.rawMoveRight.justPressed) + { + num3 = 2; + } + if (base.inputBank.rawMoveLeft.justPressed) + { + num3 = 3; + } + if (seekerController.meditationInputStep > 4) + { + meditationSuccess = true; + meditationWrapUp = true; + } + if (num3 == seekerController.GetNextMeditationStep()) + { + if (!wrapUpAnimationPlayed && seekerController.meditationInputStep < 5) + { + Util.PlaySound(inputCorrectSoundString, base.gameObject); + seekerController.meditationInputStep++; + } + } + else if (num3 != -1) + { + Util.PlaySound(inputFailSoundString, base.gameObject); + base.fixedAge += timePenalty; + } + if (base.fixedAge > 0.4f) + { + base.characterMotor.velocity = new Vector3(0f, 0f, 0f); + if (base.inputBank.skill4.justPressed) + { + meditationWrapUp = true; + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform && !spawnedLotus) + { + spawnedLotus = true; + lotusChildLocator = modelTransform.GetComponent(); + lotus = Object.Instantiate(lotusPrefab, lotusChildLocator.FindChild("Lotus"), worldPositionStays: false); + } + } + if (base.fixedAge > duration) + { + failed = true; + meditationWrapUp = true; + } + else + { + UpdateUI(); + } + } + + private void SetupInputUIIcons() + { + for (int i = 0; i < 5; i++) + { + switch (seekerController.meditationStepAndSequence[i + 1]) + { + case 0: + overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, 0f); + break; + case 1: + overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, -180f); + break; + case 2: + overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, -90f); + break; + case 3: + overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, -270f); + break; + } + } + UpdateUIInputSequence(); + } + + private void UpdateUIInputSequence() + { + if (base.isAuthority) + { + Color32 color = new Color32(byte.MaxValue, 233, 124, byte.MaxValue); + for (int i = 0; i < seekerController.meditationInputStep; i++) + { + overlayInstanceChildLocator.FindChild(c[i]).GetComponent().color = color; + } + } + } + + private void UpdateUI() + { + foreach (ImageFillController fillUi in fillUiList) + { + fillUi.SetTValue(base.fixedAge / duration); + } + } + + public override void OnExit() + { + PlayAnimation("FullBody, Override", "Empty"); + Util.PlaySound(stopSoundString, base.gameObject); + if (overlayController != null) + { + HudOverlayManager.RemoveOverlay(overlayController); + overlayController = null; + } + aimRequest?.Dispose(); + crosshairOverrideRequest?.Dispose(); + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount--; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + } + if ((bool)lotus) + { + lotus.GetComponent().duration = 0.01f; + } + if (failed) + { + base.skillLocator.special.temporaryCooldownPenalty += failureCooldownPenalty; + } + bodyStateMachine.SetNextStateToMain(); + base.OnExit(); + } + + private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) + { + fillUiList.Add(instance.GetComponent()); + overlayInstanceChildLocator = instance.GetComponent(); + SetupInputUIIcons(); + } + + private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) + { + fillUiList.Remove(instance.GetComponent()); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/SeekerInitialWeaponState.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SeekerInitialWeaponState.cs new file mode 100644 index 0000000..3639d8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SeekerInitialWeaponState.cs @@ -0,0 +1,42 @@ +using RoR2; +using RoR2.Skills; +using RoR2.UI; + +namespace EntityStates.Seeker; + +public class SeekerInitialWeaponState : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + GenericSkill genericSkill = base.skillLocator.FindSkillByFamilyName("SeekerBodyPrimaryFamily"); + if (genericSkill == null) + { + outer.SetNextStateToMain(); + return; + } + SeekerWeaponSkillDef seekerWeaponSkillDef = genericSkill.skillDef as SeekerWeaponSkillDef; + if (seekerWeaponSkillDef == null) + { + outer.SetNextStateToMain(); + return; + } + HandleCrosshair(seekerWeaponSkillDef); + HandleTargetTracking(seekerWeaponSkillDef); + outer.SetNextStateToMain(); + } + + private void HandleTargetTracking(SeekerWeaponSkillDef seekerWeapon) + { + HuntressTracker component = GetComponent(); + if (!(component == null)) + { + component.enabled = seekerWeapon.targetTrackingIndicator; + } + } + + private void HandleCrosshair(SeekerWeaponSkillDef seekerWeapon) + { + CrosshairUtils.RequestOverrideForBody(base.characterBody, seekerWeapon.crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/Sojourn.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/Sojourn.cs new file mode 100644 index 0000000..387102d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/Sojourn.cs @@ -0,0 +1,110 @@ +using RoR2; +using RoR2.PostProcessing; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Seeker; + +public class Sojourn : BaseState +{ + [SerializeField] + public GameObject vehiclePrefab; + + public static float smallHopVelocity; + + public static Color screenDamageColor; + + public static bool combineTintAdditively; + + public static float minimumDamageStrength; + + public static float maximumDamageStrength; + + public static float pulseDuration; + + private SeekerController seekerController; + + public float duration = 0.3f; + + private bool animFinished; + + private ScreenDamageCalculatorSojourn screenDamageCalculator; + + public override void OnEnter() + { + if (NetworkServer.active) + { + base.characterBody.AddBuff(DLC2Content.Buffs.SojournVehicle); + } + screenDamageCalculator = new ScreenDamageCalculatorSojourn(); + screenDamageCalculator.minimumDamage = minimumDamageStrength; + screenDamageCalculator.maximumDamage = maximumDamageStrength; + screenDamageCalculator.duration = pulseDuration; + ScreenDamageData screenDamageData = screenDamageCalculator.screenDamageData; + screenDamageData.IntendedTintColor = screenDamageColor; + screenDamageData.combineAdditively = combineTintAdditively; + base.characterBody.healthComponent.screenDamageCalculator = screenDamageCalculator; + seekerController = base.characterBody.transform.GetComponent(); + seekerController.doesExitVehicle = false; + SmallHop(base.characterMotor, smallHopVelocity); + PlayAnimation("Gesture, Override", "SojournEnterTransform"); + base.fixedAge = 0f; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration && !animFinished) + { + if (NetworkServer.active) + { + Ray aimRay = GetAimRay(); + GameObject gameObject = Object.Instantiate(vehiclePrefab, aimRay.origin, Quaternion.LookRotation(aimRay.direction)); + gameObject.GetComponent().sojournState = this; + gameObject.GetComponent().AssignPassenger(base.gameObject); + NetworkUser networkUser = base.characterBody?.master?.playerCharacterMasterController?.networkUser; + if ((bool)networkUser) + { + NetworkServer.SpawnWithClientAuthority(gameObject, networkUser.gameObject); + } + else + { + NetworkServer.Spawn(gameObject); + } + } + animFinished = true; + } + if (seekerController.doesExitVehicle) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Vehicle; + } + + public override void OnExit() + { + PlayAnimation("Gesture, Override", "SojournExitTransformation"); + if (screenDamageCalculator != null) + { + screenDamageCalculator.End(); + } + base.characterBody.healthComponent.screenDamageCalculator = null; + if (!NetworkServer.active) + { + return; + } + base.characterBody.RemoveBuff(DLC2Content.Buffs.SojournVehicle); + if (base.characterBody.HasBuff(DLC2Content.Buffs.SojournHealing)) + { + float num = base.characterBody.GetBuffCount(DLC2Content.Buffs.SojournHealing); + for (int i = 0; (float)i < num; i++) + { + base.characterBody.RemoveBuff(DLC2Content.Buffs.SojournHealing); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/SoulSearch.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SoulSearch.cs new file mode 100644 index 0000000..46dab14 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SoulSearch.cs @@ -0,0 +1,185 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Seeker; + +public class SoulSearch : BaseState, SteppedSkillDef.IStepSetter +{ + public enum Gauntlet + { + Left, + Right + } + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force = 20f; + + public static float attackSpeedAltAnimationThreshold; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float attackSoundPitch; + + public static float bloom; + + [SerializeField] + public GameObject blastEffectPrefab; + + [SerializeField] + public GameObject blastImpactEffectPrefab; + + [SerializeField] + public float blastRadius; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastForce; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public float blastProcCoefficient; + + private float duration; + + private bool hasFiredGauntlet; + + private string muzzleString; + + private Transform muzzleTransform; + + private Animator animator; + + private ChildLocator childLocator; + + private Gauntlet gauntlet; + + private HuntressTracker huntressTracker; + + public void SetStep(int i) + { + gauntlet = (Gauntlet)i; + } + + public override void OnEnter() + { + base.OnEnter(); + huntressTracker = base.characterBody.GetComponent(); + if (!huntressTracker.GetTrackingTarget()) + { + outer.SetNextStateToMain(); + return; + } + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSoundPitch); + base.characterBody.SetAimTimer(2f); + animator = GetModelAnimator(); + if ((bool)animator) + { + childLocator = animator.GetComponent(); + } + switch (gauntlet) + { + case Gauntlet.Left: + muzzleString = "MuzzleLeft"; + PlayCrossfade("Gesture, Additive", "Cast1Left", "FireGauntlet.playbackRate", duration, 0.1f); + PlayCrossfade("Gesture, Override", "Cast1Left", "FireGauntlet.playbackRate", duration, 0.1f); + break; + case Gauntlet.Right: + muzzleString = "MuzzleRight"; + PlayCrossfade("Gesture, Additive", "Cast1Right", "FireGauntlet.playbackRate", duration, 0.1f); + PlayCrossfade("Gesture, Override", "Cast1Right", "FireGauntlet.playbackRate", duration, 0.1f); + break; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireGauntlet() + { + if (!hasFiredGauntlet) + { + base.characterBody.AddSpreadBloom(bloom); + Ray aimRay = GetAimRay(); + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild(muzzleString); + } + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (projectilePrefab != null && base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = muzzleTransform.position; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(aimRay.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration || hasFiredGauntlet) + { + if (!hasFiredGauntlet && (bool)huntressTracker.GetTrackingTarget()) + { + FireGauntlet(); + hasFiredGauntlet = true; + } + if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)gauntlet); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + gauntlet = (Gauntlet)reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/SoulSpiral.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SoulSpiral.cs new file mode 100644 index 0000000..dca9c63 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SoulSpiral.cs @@ -0,0 +1,108 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class SoulSpiral : BaseState +{ + public static string prepOrbSoundString; + + public static float duration; + + public static float dmgCoefficient; + + public static GameObject projectilePrefab; + + public static GameObject muzzleFXPrefab; + + public static string muzzleChildName; + + public static float projectileForce; + + public static float smallHopVelocity; + + public bool firedOrb; + + private EffectData effectData; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.modelLocator) + { + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + int childIndex = component.FindChildIndex(muzzleChildName); + effectData = new EffectData(); + effectData.SetChildLocatorTransformReference(base.characterBody.gameObject, childIndex); + } + } + PlayAnimation("Gesture, Additive", "SoulSpiralStart", "PrepUnseenHand.playbackRate", duration); + PlayAnimation("Gesture, Override", "SoulSpiralStart", "PrepUnseenHand.playbackRate", duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!firedOrb && base.fixedAge > duration && base.isAuthority) + { + FireSpiral(); + outer.SetNextStateToMain(); + } + } + + private void FireSpiral() + { + firedOrb = true; + Util.PlaySound(prepOrbSoundString, base.gameObject); + effectData.origin = base.characterBody.corePosition; + effectData.rotation = Quaternion.identity; + EffectManager.SpawnEffect(muzzleFXPrefab, effectData, transmit: false); + if (base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * dmgCoefficient; + fireProjectileInfo.force = projectileForce; + fireProjectileInfo.position = base.characterBody.corePosition; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + FireProjectileInfo projectileInfo = fireProjectileInfo; + base.characterBody.GetComponent().FireSoulSpiral(projectileInfo); + } + } + + public override void OnExit() + { + base.OnExit(); + if (!firedOrb && !ObjectIsBeingDestroyed()) + { + FireSpiral(); + } + if ((bool)base.characterMotor && !base.isGrounded) + { + base.characterMotor.velocity = new Vector3(base.characterMotor.velocity.x, Mathf.Max(base.characterMotor.velocity.y, smallHopVelocity), base.characterMotor.velocity.z); + } + } + + private bool ObjectIsBeingDestroyed() + { + GameObject gameObject = base.characterBody.gameObject; + if (!(gameObject == null)) + { + if (!gameObject.activeSelf) + { + return gameObject.activeInHierarchy; + } + return false; + } + return true; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/SpiritPunch.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SpiritPunch.cs new file mode 100644 index 0000000..0a7e124 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/SpiritPunch.cs @@ -0,0 +1,201 @@ +using System; +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Seeker; + +public class SpiritPunch : BaseState, SteppedSkillDef.IStepSetter +{ + public enum Gauntlet + { + Left, + Right, + Explode + } + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject projectileFinisherPrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float dmgBuffIncrease = 0.2f; + + [SerializeField] + public float comboDamageCoefficient; + + [SerializeField] + public float force = 20f; + + public static float attackSpeedAltAnimationThreshold; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float paddingBetweenAttacks = 0.2f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public string attackSoundStringAlt; + + [SerializeField] + public float attackSoundPitch; + + [SerializeField] + public float bloom; + + private float duration; + + private bool hasFiredGauntlet; + + private string muzzleString; + + private Transform muzzleTransform; + + private Animator animator; + + private ChildLocator childLocator; + + private Gauntlet gauntlet; + + private float extraDmgFromBuff; + + public static float recoilAmplitude; + + private string animationStateName; + + public static event Action onSpiritOrbFired; + + public void SetStep(int i) + { + gauntlet = (Gauntlet)i; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + base.characterBody.SetAimTimer(2f); + animator = GetModelAnimator(); + if ((bool)animator) + { + childLocator = animator.GetComponent(); + } + switch (gauntlet) + { + case Gauntlet.Left: + muzzleString = "MuzzleLeft"; + animationStateName = "Cast1Left"; + break; + case Gauntlet.Right: + muzzleString = "MuzzleRight"; + animationStateName = "Cast1Right"; + break; + case Gauntlet.Explode: + muzzleString = "MuzzleEnergyBomb"; + animationStateName = "SpiritPunchFinisher"; + extraDmgFromBuff = dmgBuffIncrease * (float)base.characterBody.GetBuffCount(DLC2Content.Buffs.ChakraBuff); + break; + } + bool @bool = animator.GetBool("isMoving"); + bool bool2 = animator.GetBool("isGrounded"); + if (!@bool && bool2) + { + PlayCrossfade("FullBody, Override", animationStateName, "FireGauntlet.playbackRate", duration, 0.025f); + return; + } + PlayCrossfade("Gesture, Additive", animationStateName, "FireGauntlet.playbackRate", duration, 0.025f); + PlayCrossfade("Gesture, Override", animationStateName, "FireGauntlet.playbackRate", duration, 0.025f); + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireGauntlet() + { + if (!hasFiredGauntlet) + { + base.characterBody.AddSpreadBloom(bloom); + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + if ((bool)childLocator) + { + muzzleTransform = childLocator.FindChild(muzzleString); + } + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if (base.isAuthority) + { + float damage = damageStat * (damageCoefficient + extraDmgFromBuff); + ProjectileManager.instance.FireProjectile(projectilePrefab, muzzleTransform.position, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damage, force, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, 70f + attackSpeedStat * 2f); + } + AddRecoil(-0.1f * recoilAmplitude, 0.1f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration - duration * 0.25f || hasFiredGauntlet) + { + if (gauntlet == Gauntlet.Explode && !hasFiredGauntlet) + { + Util.PlayAttackSpeedSound(attackSoundStringAlt, base.gameObject, attackSoundPitch); + projectilePrefab = projectileFinisherPrefab; + damageCoefficient = comboDamageCoefficient; + FireGauntlet(); + SpiritPunch.onSpiritOrbFired?.Invoke(obj: true); + _ = base.characterMotor.isGrounded; + hasFiredGauntlet = true; + } + else if (!hasFiredGauntlet) + { + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, attackSoundPitch); + FireGauntlet(); + hasFiredGauntlet = true; + SpiritPunch.onSpiritOrbFired?.Invoke(obj: false); + } + if (base.isAuthority && base.fixedAge >= duration + duration * paddingBetweenAttacks) + { + outer.SetNextStateToMain(); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)gauntlet); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + gauntlet = (Gauntlet)reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Seeker/UnseenHand.cs b/ilspy_dump/ror2_csproj/EntityStates.Seeker/UnseenHand.cs new file mode 100644 index 0000000..08e7f3e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Seeker/UnseenHand.cs @@ -0,0 +1,198 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Seeker; + +public class UnseenHand : BaseState +{ + public static float baseDuration; + + public static GameObject areaIndicatorPrefab; + + public static GameObject projectilePrefab; + + public static GameObject muzzleflashEffect; + + public static GameObject goodCrosshairPrefab; + + public static GameObject badCrosshairPrefab; + + public static string prepFistSoundString; + + public static string endFistSoundString; + + public static string startTargetingLoopSoundString; + + public static string stopTargetingLoopSoundString; + + public static float maxDistance; + + public static string fireSoundString; + + public static float maxSlopeAngle; + + public static GameObject initialEffect; + + public static GameObject muzzleFlashEffect; + + public static GameObject fistProjectilePrefab; + + public static float fistDamageCoefficient; + + public static float fistForce; + + public static float fuseOverride; + + public static int abilityAimType; + + public static float cameraTransitionOutTime; + + public static float smallHopVelocity; + + private float duration; + + private float stopwatch; + + private bool goodPlacement; + + private GameObject areaIndicatorInstance; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + protected CameraTargetParams.AimRequest aimRequest; + + private bool cameraStarted; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + base.characterBody.SetAimTimer(duration + 2f); + PlayAnimation("Gesture, Additive", "UnseenHandPrep", "PrepUnseenHand.playbackRate", duration); + PlayAnimation("Gesture, Override", "UnseenHandPrep", "PrepUnseenHand.playbackRate", duration); + Util.PlaySound(prepFistSoundString, base.gameObject); + Util.PlaySound(startTargetingLoopSoundString, base.gameObject); + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab); + UpdateAreaIndicator(); + } + + private void UpdateAreaIndicator() + { + bool flag = goodPlacement; + goodPlacement = false; + areaIndicatorInstance.SetActive(value: true); + if ((bool)areaIndicatorInstance) + { + float num = maxDistance; + float extraRaycastDistance = 0f; + if (Physics.Raycast(CameraRigController.ModifyAimRayIfApplicable(GetAimRay(), base.gameObject, out extraRaycastDistance), out var hitInfo, num + extraRaycastDistance, LayerIndex.world.mask)) + { + areaIndicatorInstance.transform.position = hitInfo.point; + goodPlacement = Vector3.Angle(Vector3.up, hitInfo.normal) < maxSlopeAngle; + } + if (flag != goodPlacement || crosshairOverrideRequest == null) + { + crosshairOverrideRequest?.Dispose(); + GameObject crosshairPrefab = (goodPlacement ? goodCrosshairPrefab : badCrosshairPrefab); + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairPrefab, CrosshairUtils.OverridePriority.Skill); + } + } + areaIndicatorInstance.SetActive(goodPlacement); + } + + public override void Update() + { + base.Update(); + UpdateAreaIndicator(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!cameraStarted && base.fixedAge > 0.1f) + { + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType((CameraTargetParams.AimType)abilityAimType); + } + cameraStarted = true; + } + if (base.inputBank.skill2.down || !base.isAuthority) + { + return; + } + if (goodPlacement) + { + PlayAnimation("Gesture, Additive", "UnseenHandFinish"); + PlayAnimation("Gesture, Override", "UnseenHandFinish"); + Util.PlaySound(fireSoundString, base.gameObject); + if ((bool)areaIndicatorInstance) + { + EffectManager.SpawnEffect(muzzleFlashEffect, new EffectData + { + origin = areaIndicatorInstance.transform.position + }, transmit: true); + if (base.isAuthority) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "MuzzleLeft", transmit: true); + EffectManager.SimpleMuzzleFlash(muzzleflashEffect, base.gameObject, "MuzzleRight", transmit: true); + Vector3 forward = areaIndicatorInstance.transform.forward; + forward.y = 0f; + forward.Normalize(); + Vector3.Cross(Vector3.up, forward); + Util.CheckRoll(critStat, base.characterBody.master); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = fistProjectilePrefab; + fireProjectileInfo.position = areaIndicatorInstance.transform.position; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(Vector3.up); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * fistDamageCoefficient; + fireProjectileInfo.damageTypeOverride = DamageType.Stun1s; + fireProjectileInfo.force = fistForce; + fireProjectileInfo.crit = base.characterBody.RollCrit(); + fireProjectileInfo.fuseOverride = fuseOverride; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + } + else + { + base.skillLocator.secondary.AddOneStock(); + PlayCrossfade("Gesture, Additive", "BufferEmpty", 0.2f); + PlayCrossfade("Gesture, Override", "BufferEmpty", 0.2f); + } + outer.SetNextStateToMain(); + } + + public override void OnExit() + { + if (goodPlacement) + { + if (!base.isGrounded) + { + base.characterMotor.velocity.y = Mathf.Max(base.characterMotor.velocity.y, smallHopVelocity); + } + if (base.characterBody.isServer) + { + CharacterBody obj = base.characterBody; + if ((object)obj != null && obj.inventory.GetItemCount(DLC2Content.Items.IncreasePrimaryDamage) > 0) + { + base.characterBody.AddIncreasePrimaryDamageStack(); + } + } + } + Util.PlaySound(endFistSoundString, base.gameObject); + Util.PlaySound(stopTargetingLoopSoundString, base.gameObject); + EntityState.Destroy(areaIndicatorInstance.gameObject); + crosshairOverrideRequest?.Dispose(); + aimRequest?.Dispose(); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteActivatedState.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteActivatedState.cs new file mode 100644 index 0000000..f186ce0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteActivatedState.cs @@ -0,0 +1,59 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteActivatedState : ShrineHalcyoniteBaseState +{ + public float shrineAnimationDuration = 1f; + + public float shrineDelayAge; + + public Vector3 shrineEndLocation = new Vector3(0f, 0f, 0f); + + private float shrineMovementTimer; + + private GameObject modelBase; + + public override void OnEnter() + { + base.OnEnter(); + Transform transform = parentShrineReference.modelChildLocator.FindChild("ModelBase"); + if ((bool)transform) + { + modelBase = transform.gameObject; + } + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/HalcyonResurfaceVFX"), new EffectData + { + origin = base.gameObject.transform.position + }, transmit: true); + Util.PlaySound("Play_obj_shrineHalcyonite_activate", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + shrineMovementTimer -= Time.deltaTime; + if (!(shrineMovementTimer <= 0f)) + { + return; + } + if (modelBase.transform.localPosition != shrineEndLocation) + { + shrineMovementTimer += 0.05f; + modelBase.transform.localPosition += new Vector3(0f, 0.1f, 0f); + if (modelBase.transform.localPosition == shrineEndLocation) + { + Util.PlaySound("Play_obj_shrineHalcyonite_activate_finish", base.gameObject); + } + } + else + { + shrineDelayAge += Time.deltaTime; + if (shrineDelayAge >= shrineAnimationDuration) + { + outer.SetNextState(new ShrineHalcyoniteNoQuality()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteBaseState.cs new file mode 100644 index 0000000..29b049c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteBaseState.cs @@ -0,0 +1,110 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteBaseState : BaseState +{ + protected HalcyoniteShrineInteractable parentShrineReference; + + protected GameObject crystalObject; + + protected ParticleSystem ps; + + protected GameObject shrineHalcyoniteBubble; + + protected GameObject shrineBase; + + private Xoroshiro128Plus rng; + + private GameObject modelBase; + + protected bool visualsDone; + + protected float timer; + + private int sliceHeightNameId; + + private Renderer shrineBaseRenderer; + + public override void OnEnter() + { + base.OnEnter(); + parentShrineReference = GetComponent(); + if ((bool)parentShrineReference) + { + shrineHalcyoniteBubble = parentShrineReference.shrineHalcyoniteBubble; + crystalObject = parentShrineReference.crystalObject; + crystalObject.GetComponent(); + shrineBase = parentShrineReference.shrineBaseObject; + } + shrineBaseRenderer = parentShrineReference.shrineGoldTop.GetComponent(); + shrineBaseRenderer.material.EnableKeyword("_SLICEHEIGHT"); + int propertyIndex = shrineBaseRenderer.material.shader.FindPropertyIndex("_SliceHeight"); + sliceHeightNameId = shrineBaseRenderer.material.shader.GetPropertyNameId(propertyIndex); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected void TierChange(float tierChangeVFXModifier) + { + Transform transform = parentShrineReference.modelChildLocator.FindChild("ModelBase"); + if ((bool)transform) + { + modelBase = transform.gameObject; + } + Vector3 origin = modelBase.gameObject.transform.position + new Vector3(0f, tierChangeVFXModifier, 0f); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/HalcyonShrineTierReachVFX"), new EffectData + { + origin = origin + }, transmit: false); + Util.PlaySound("Play_obj_shrineHalcyonite_tierChange", base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + parentShrineReference.shrineGoldTop.GetComponent().material.SetFloat(sliceHeightNameId, parentShrineReference.goldMaterialModifier); + } + + protected void ModifyVisuals() + { + if (!NetworkServer.active || visualsDone || !parentShrineReference.isDraining) + { + return; + } + float num = 4.1f; + float num2 = 3.5f; + float num3 = 4f; + float num4 = (float)parentShrineReference.goldDrainValue * num / (float)parentShrineReference.lowGoldCost; + if (parentShrineReference.goldDrained < parentShrineReference.lowGoldCost || parentShrineReference.goldMaterialModifier < 1.9f) + { + HalcyoniteShrineInteractable halcyoniteShrineInteractable = parentShrineReference; + halcyoniteShrineInteractable.NetworkgoldMaterialModifier = halcyoniteShrineInteractable.goldMaterialModifier + num4; + } + if ((parentShrineReference.goldDrained > parentShrineReference.lowGoldCost && parentShrineReference.goldDrained < parentShrineReference.midGoldCost) || (parentShrineReference.goldMaterialModifier < 6f && parentShrineReference.goldMaterialModifier >= 1.9f)) + { + num4 = (float)parentShrineReference.goldDrainValue * num2 / (float)(parentShrineReference.midGoldCost - parentShrineReference.lowGoldCost); + if (parentShrineReference.goldMaterialModifier >= 5f) + { + num4 = (float)parentShrineReference.goldDrainValue * num3 / (float)(parentShrineReference.maxGoldCost - parentShrineReference.midGoldCost); + } + HalcyoniteShrineInteractable halcyoniteShrineInteractable2 = parentShrineReference; + halcyoniteShrineInteractable2.NetworkgoldMaterialModifier = halcyoniteShrineInteractable2.goldMaterialModifier + num4; + } + if ((parentShrineReference.goldDrained > parentShrineReference.midGoldCost && parentShrineReference.goldDrained < parentShrineReference.maxGoldCost) || parentShrineReference.goldMaterialModifier >= 6f) + { + num4 = (float)parentShrineReference.goldDrainValue * num3 / (float)(parentShrineReference.maxGoldCost - parentShrineReference.midGoldCost); + HalcyoniteShrineInteractable halcyoniteShrineInteractable3 = parentShrineReference; + halcyoniteShrineInteractable3.NetworkgoldMaterialModifier = halcyoniteShrineInteractable3.goldMaterialModifier + num4; + } + if (parentShrineReference.goldDrained >= parentShrineReference.maxGoldCost) + { + visualsDone = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteFinished.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteFinished.cs new file mode 100644 index 0000000..fd5052f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteFinished.cs @@ -0,0 +1,16 @@ +using RoR2; + +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteFinished : ShrineHalcyoniteBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + if (shrineHalcyoniteBubble.activeInHierarchy) + { + Util.PlaySound("Stop_obj_shrineHalcyonite_idle_loop", base.gameObject); + shrineHalcyoniteBubble.SetActive(value: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteLowQuality.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteLowQuality.cs new file mode 100644 index 0000000..99b18a3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteLowQuality.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteLowQuality : ShrineHalcyoniteBaseState +{ + [SerializeField] + public float tierChangeMonsterCreditReduction; + + public override void OnEnter() + { + base.OnEnter(); + GoldSiphonNearbyBodyController.onHalcyonShrineGoldDrain += base.ModifyVisuals; + TierChange(5f); + parentShrineReference.activationDirector.monsterCredit += parentShrineReference.monsterCredit - tierChangeMonsterCreditReduction; + parentShrineReference.activationDirector.SpendAllCreditsOnMapSpawns(parentShrineReference.gameObject.transform); + } + + public override void OnExit() + { + base.OnExit(); + GoldSiphonNearbyBodyController.onHalcyonShrineGoldDrain -= base.ModifyVisuals; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteMaxQuality.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteMaxQuality.cs new file mode 100644 index 0000000..8ba7081 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteMaxQuality.cs @@ -0,0 +1,11 @@ +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteMaxQuality : ShrineHalcyoniteBaseState +{ + public override void OnEnter() + { + base.OnEnter(); + parentShrineReference.shrineGoldTop.SetActive(value: true); + parentShrineReference.DrainConditionMet(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteMidQuality.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteMidQuality.cs new file mode 100644 index 0000000..672be6a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteMidQuality.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteMidQuality : ShrineHalcyoniteBaseState +{ + [SerializeField] + public float tierChangeMonsterCreditReduction; + + public override void OnEnter() + { + base.OnEnter(); + TierChange(8f); + GoldSiphonNearbyBodyController.onHalcyonShrineGoldDrain += base.ModifyVisuals; + parentShrineReference.activationDirector.monsterCredit += parentShrineReference.monsterCredit - tierChangeMonsterCreditReduction; + parentShrineReference.activationDirector.SpendAllCreditsOnMapSpawns(parentShrineReference.gameObject.transform); + } + + public override void OnExit() + { + base.OnExit(); + GoldSiphonNearbyBodyController.onHalcyonShrineGoldDrain -= base.ModifyVisuals; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteNoQuality.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteNoQuality.cs new file mode 100644 index 0000000..39b0b7f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineHalcyonite/ShrineHalcyoniteNoQuality.cs @@ -0,0 +1,27 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ShrineHalcyonite; + +public class ShrineHalcyoniteNoQuality : ShrineHalcyoniteBaseState +{ + [SerializeField] + public float tierChangeMonsterCreditReduction; + + public override void OnEnter() + { + base.OnEnter(); + parentShrineReference.TrackInteractions(); + shrineHalcyoniteBubble.SetActive(value: true); + parentShrineReference.activationDirector.monsterCredit += parentShrineReference.monsterCredit - tierChangeMonsterCreditReduction; + parentShrineReference.activationDirector.SpendAllCreditsOnMapSpawns(parentShrineReference.gameObject.transform); + GoldSiphonNearbyBodyController.onHalcyonShrineGoldDrain += base.ModifyVisuals; + Util.PlaySound("Play_obj_shrineHalcyonite_idle_loop", base.gameObject); + } + + public override void OnExit() + { + base.OnExit(); + GoldSiphonNearbyBodyController.onHalcyonShrineGoldDrain -= base.ModifyVisuals; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthChoice.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthChoice.cs new file mode 100644 index 0000000..eee2c36 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthChoice.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ShrineRebirth; + +public class RebirthChoice : ShrineRebirthEntityStates +{ + public float rebirthGameEndingTransition = 15f; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound("Play_obj_shrineColossus_locked_loop", base.gameObject); + Transform transform = _shrineController.childLocator.FindChild("TriggeredVFXSpawnPoint"); + GameObject effectPrefab = LegacyResourcesAPI.Load("Prefabs/Effects/RebirthOnRebirthVFX"); + EffectData effectData = new EffectData + { + origin = transform.position, + genericFloat = 1.5f + }; + effectData.SetNetworkedObjectReference(base.gameObject); + int childIndex = _shrineController.childLocator.FindChildIndex("TriggeredVFXSpawnPoint"); + effectData.SetChildLocatorTransformReference(base.gameObject, childIndex); + if (NetworkServer.active) + { + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + _ = base.fixedAge; + _ = rebirthGameEndingTransition; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthOrPortalChoice.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthOrPortalChoice.cs new file mode 100644 index 0000000..51083ac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthOrPortalChoice.cs @@ -0,0 +1,30 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.ShrineRebirth; + +public class RebirthOrPortalChoice : ShrineRebirthEntityStates +{ + public override void OnEnter() + { + base.OnEnter(); + _shrineController.onRebirthOrContinueTextObject.SetActive(value: true); + _shrineController.CallRpcChangeInteractScript(); + GameObject gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(_shrineController.helminthPortalISC, new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Direct, + position = _shrineController.portalObject.transform.position, + spawnOnTarget = _shrineController.portalObject.transform + }, Run.instance.stageRng)); + if ((bool)gameObject) + { + gameObject.transform.rotation = _shrineController.portalObject.transform.rotation; + } + } + + public override void OnExit() + { + base.OnExit(); + _shrineController.onRebirthOrContinueTextObject.SetActive(value: true); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthStormEnding.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthStormEnding.cs new file mode 100644 index 0000000..5ed89a4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RebirthStormEnding.cs @@ -0,0 +1,9 @@ +namespace EntityStates.ShrineRebirth; + +public class RebirthStormEnding : ShrineRebirthEntityStates +{ + public override void OnEnter() + { + base.OnEnter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RevealRebirthShriine.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RevealRebirthShriine.cs new file mode 100644 index 0000000..57918b4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/RevealRebirthShriine.cs @@ -0,0 +1,50 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.ShrineRebirth; + +public class RevealRebirthShriine : ShrineRebirthEntityStates +{ + [SyncVar] + private GameObject shrineModel; + + public override void OnEnter() + { + base.OnEnter(); + if (Run.instance.selectedDifficulty < DifficultyIndex.Eclipse1) + { + _shrineController.purchaseInteraction.SetAvailable(newAvailable: true); + _shrineController.onShrineRevealObjectiveTextObject.SetActive(value: true); + Transform transform = _shrineController.childLocator.FindChild("ShrineModel"); + if ((bool)transform) + { + shrineModel = transform.gameObject; + if (!shrineModel.activeInHierarchy) + { + shrineModel.SetActive(value: true); + } + } + return; + } + Transform transform2 = _shrineController.childLocator.FindChild("ShrineModel"); + shrineModel = transform2.gameObject; + shrineModel.SetActive(value: false); + GameObject gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(_shrineController.helminthPortalISC, new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Direct, + position = _shrineController.portalObject.transform.position, + spawnOnTarget = _shrineController.portalObject.transform + }, Run.instance.stageRng)); + if ((bool)gameObject) + { + gameObject.transform.rotation = _shrineController.portalObject.transform.rotation; + } + } + + public override void OnExit() + { + _shrineController.onShrineRevealObjectiveTextObject.SetActive(value: false); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/ShrineRebirthEntityStates.cs b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/ShrineRebirthEntityStates.cs new file mode 100644 index 0000000..7e83fdc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.ShrineRebirth/ShrineRebirthEntityStates.cs @@ -0,0 +1,29 @@ +using RoR2; + +namespace EntityStates.ShrineRebirth; + +public class ShrineRebirthEntityStates : EntityState +{ + protected ShrineRebirthController _shrineController; + + protected PickupPickerController _pickupPickerController; + + protected PurchaseInteraction _pi; + + protected NetworkUIPromptController _netUIPromptController; + + public override void OnEnter() + { + base.OnEnter(); + _shrineController = base.gameObject.GetComponent(); + if (_shrineController.isForTesting) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/BaseSiphonItemState.cs b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/BaseSiphonItemState.cs new file mode 100644 index 0000000..4d634e0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/BaseSiphonItemState.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.SiphonItem; + +public class BaseSiphonItemState : BaseBodyAttachmentState +{ + private List FXParticles = new List(); + + protected int GetItemStack() + { + if (!base.attachedBody || !base.attachedBody.inventory) + { + return 1; + } + return base.attachedBody.inventory.GetItemCount(RoR2Content.Items.SiphonOnLowHealth); + } + + public override void OnEnter() + { + base.OnEnter(); + FXParticles = base.gameObject.GetComponentsInChildren().ToList(); + } + + public void TurnOffHealingFX() + { + for (int i = 0; i < FXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = FXParticles[i].emission; + emission.enabled = false; + } + } + + public void TurnOnHealingFX() + { + for (int i = 0; i < FXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = FXParticles[i].emission; + emission.enabled = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/ChargeState.cs b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/ChargeState.cs new file mode 100644 index 0000000..75b4339 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/ChargeState.cs @@ -0,0 +1,76 @@ +using EntityStates.VagrantMonster; +using RoR2; +using UnityEngine; + +namespace EntityStates.SiphonItem; + +public class ChargeState : BaseSiphonItemState +{ + public static float baseDuration = 3f; + + public static string chargeSound; + + private float duration; + + private GameObject chargeVfxInstance; + + private GameObject areaIndicatorVfxInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / (base.attachedBody ? base.attachedBody.attackSpeed : 1f); + TurnOffHealingFX(); + if ((bool)base.attachedBody) + { + Vector3 position = base.transform.position; + Quaternion rotation = base.transform.rotation; + chargeVfxInstance = Object.Instantiate(ChargeMegaNova.chargingEffectPrefab, position, rotation); + chargeVfxInstance.transform.localScale = Vector3.one * 0.25f; + Util.PlaySound(chargeSound, base.gameObject); + areaIndicatorVfxInstance = Object.Instantiate(ChargeMegaNova.areaIndicatorPrefab, position, rotation); + ObjectScaleCurve component = areaIndicatorVfxInstance.GetComponent(); + component.timeMax = duration; + component.baseScale = Vector3.one * DetonateState.baseSiphonRange * 2f; + areaIndicatorVfxInstance.GetComponent().timeMax = duration; + } + RoR2Application.onLateUpdate += OnLateUpdate; + } + + public override void OnExit() + { + RoR2Application.onLateUpdate -= OnLateUpdate; + if ((object)chargeVfxInstance != null) + { + EntityState.Destroy(chargeVfxInstance); + chargeVfxInstance = null; + } + if ((object)areaIndicatorVfxInstance != null) + { + EntityState.Destroy(areaIndicatorVfxInstance); + areaIndicatorVfxInstance = null; + } + base.OnExit(); + } + + private void OnLateUpdate() + { + if ((bool)chargeVfxInstance) + { + chargeVfxInstance.transform.position = base.transform.position; + } + if ((bool)areaIndicatorVfxInstance) + { + areaIndicatorVfxInstance.transform.position = base.transform.position; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new DetonateState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/DetonateState.cs b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/DetonateState.cs new file mode 100644 index 0000000..e464c0f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/DetonateState.cs @@ -0,0 +1,123 @@ +using RoR2; +using RoR2.Orbs; +using UnityEngine; + +namespace EntityStates.SiphonItem; + +public class DetonateState : BaseSiphonItemState +{ + public static float baseSiphonRange = 50f; + + public static float baseDuration; + + public static float healPulseFraction = 0.5f; + + public static float healMultiplier = 2f; + + public static float damageFraction = 0.1f; + + public static GameObject burstEffectPrefab; + + public static string explosionSound; + + public static string siphonLoopSound; + + public static string retractSound; + + private float duration; + + private float gainedHealth; + + private float gainedHealthFraction; + + private float healTimer; + + private bool burstPlayed; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + GetItemStack(); + Vector3 position = base.attachedBody.transform.position; + SphereSearch obj = new SphereSearch + { + origin = position, + radius = baseSiphonRange, + mask = LayerIndex.entityPrecise.mask + }; + float num = base.attachedBody.healthComponent.fullCombinedHealth * damageFraction; + TeamMask mask = default(TeamMask); + mask.AddTeam(base.attachedBody.teamComponent.teamIndex); + HurtBox[] hurtBoxes = obj.RefreshCandidates().FilterCandidatesByHurtBoxTeam(mask).OrderCandidatesByDistance() + .FilterCandidatesByDistinctHurtBoxEntities() + .GetHurtBoxes(); + foreach (HurtBox hurtBox in hurtBoxes) + { + if (hurtBox.healthComponent != base.attachedBody.healthComponent) + { + if (!burstPlayed) + { + burstPlayed = true; + Util.PlaySound(explosionSound, base.gameObject); + Util.PlaySound(siphonLoopSound, base.gameObject); + EffectData effectData = new EffectData + { + scale = 1f, + origin = position + }; + effectData.SetHurtBoxReference(base.attachedBody.modelLocator.modelTransform.GetComponent().FindChild("Base").gameObject); + EffectManager.SpawnEffect(burstEffectPrefab, effectData, transmit: false); + } + DamageInfo damageInfo = new DamageInfo + { + attacker = base.attachedBody.gameObject, + inflictor = base.attachedBody.gameObject, + crit = false, + damage = num, + damageColorIndex = DamageColorIndex.Default, + damageType = DamageType.Generic, + force = Vector3.zero, + position = hurtBox.transform.position + }; + hurtBox.healthComponent.TakeDamage(damageInfo); + HurtBox hurtBoxReference = hurtBox; + HurtBoxGroup hurtBoxGroup = hurtBox.hurtBoxGroup; + for (int j = 0; (float)j < Mathf.Min(4f, base.attachedBody.radius * 2f); j++) + { + EffectData effectData2 = new EffectData + { + scale = 1f, + origin = position, + genericFloat = 3f + }; + effectData2.SetHurtBoxReference(hurtBoxReference); + GameObject obj2 = LegacyResourcesAPI.Load("Prefabs/Effects/OrbEffects/SiphonOrbEffect"); + obj2.GetComponent().parentObjectTransform = base.attachedBody.mainHurtBox.transform; + EffectManager.SpawnEffect(obj2, effectData2, transmit: true); + hurtBoxReference = hurtBoxGroup.hurtBoxes[Random.Range(0, hurtBoxGroup.hurtBoxes.Length)]; + } + gainedHealth += num; + } + } + gainedHealthFraction = gainedHealth * healPulseFraction; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + healTimer += GetDeltaTime(); + if (base.isAuthority && healTimer > duration * healPulseFraction && gainedHealth > 0f) + { + base.attachedBody.healthComponent.Heal(gainedHealthFraction, default(ProcChainMask)); + TurnOnHealingFX(); + healTimer = 0f; + if (base.fixedAge >= duration) + { + Util.PlaySound(retractSound, base.gameObject); + TurnOffHealingFX(); + outer.SetNextState(new RechargeState()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/ReadyState.cs b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/ReadyState.cs new file mode 100644 index 0000000..3b709f6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/ReadyState.cs @@ -0,0 +1,26 @@ +using RoR2; + +namespace EntityStates.SiphonItem; + +public class ReadyState : BaseSiphonItemState +{ + public static float healthFractionThreshold = 0.5f; + + private HealthComponent attachedHealthComponent; + + public override void OnEnter() + { + base.OnEnter(); + attachedHealthComponent = base.attachedBody?.healthComponent; + TurnOffHealingFX(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && attachedHealthComponent.combinedHealthFraction <= healthFractionThreshold) + { + outer.SetNextState(new ChargeState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/RechargeState.cs b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/RechargeState.cs new file mode 100644 index 0000000..b6add72 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SiphonItem/RechargeState.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +namespace EntityStates.SiphonItem; + +public class RechargeState : BaseSiphonItemState +{ + public static float baseDuration = 30f; + + public static AnimationCurve particleEmissionCurve; + + private float rechargeDuration; + + public override void OnEnter() + { + base.OnEnter(); + TurnOffHealingFX(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + int itemStack = GetItemStack(); + float num = baseDuration / (float)(itemStack + 1); + if (base.fixedAge / num >= 1f) + { + outer.SetNextState(new ReadyState()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Sniper.Scope/ScopeSniper.cs b/ilspy_dump/ror2_csproj/EntityStates.Sniper.Scope/ScopeSniper.cs new file mode 100644 index 0000000..ce056cb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Sniper.Scope/ScopeSniper.cs @@ -0,0 +1,72 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Sniper.Scope; + +public class ScopeSniper : BaseState +{ + public static float baseChargeDuration = 4f; + + public static GameObject crosshairPrefab; + + public float charge; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private GameObject laserPointerObject; + + private CameraTargetParams.AimRequest aimRequest; + + public override void OnEnter() + { + base.OnEnter(); + charge = 0f; + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Slow50); + } + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.FirstPerson); + base.cameraTargetParams.fovOverride = 20f; + } + if ((bool)crosshairPrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairPrefab, CrosshairUtils.OverridePriority.Skill); + } + laserPointerObject = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/LaserPointerBeamEnd")); + laserPointerObject.GetComponent().source = base.inputBank; + } + + public override void OnExit() + { + EntityState.Destroy(laserPointerObject); + if (NetworkServer.active && (bool)base.characterBody) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Slow50); + } + aimRequest?.Dispose(); + if ((bool)base.cameraTargetParams) + { + base.cameraTargetParams.fovOverride = -1f; + } + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + public override void FixedUpdate() + { + charge = Mathf.Min(charge + attackSpeedStat / baseChargeDuration * GetDeltaTime(), 1f); + if (base.isAuthority && (!base.inputBank || !base.inputBank.skill2.down)) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Sniper.SniperWeapon/FireRifle.cs b/ilspy_dump/ror2_csproj/EntityStates.Sniper.SniperWeapon/FireRifle.cs new file mode 100644 index 0000000..29b145e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Sniper.SniperWeapon/FireRifle.cs @@ -0,0 +1,127 @@ +using EntityStates.Sniper.Scope; +using RoR2; +using UnityEngine; + +namespace EntityStates.Sniper.SniperWeapon; + +public class FireRifle : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float minChargeDamageCoefficient; + + public static float maxChargeDamageCoefficient; + + public static float minChargeForce; + + public static float maxChargeForce; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackSoundString; + + public static float recoilAmplitude; + + public static float spreadBloomValue = 0.3f; + + public static float interruptInterval = 0.2f; + + private float duration; + + private bool inputReleased; + + private static int FireShotgunStateHash = Animator.StringToHash("FireShotgun"); + + private static int FireShotgunParamHash = Animator.StringToHash("FireShotgun.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + float num = 0f; + if ((bool)base.skillLocator) + { + GenericSkill secondary = base.skillLocator.secondary; + if ((bool)secondary) + { + EntityStateMachine stateMachine = secondary.stateMachine; + if ((bool)stateMachine && stateMachine.state is ScopeSniper scopeSniper) + { + num = scopeSniper.charge; + scopeSniper.charge = 0f; + } + } + } + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + Util.PlaySound(attackSoundString, base.gameObject); + PlayAnimation("Gesture", FireShotgunStateHash, FireShotgunParamHash, duration * 1.1f); + string muzzleName = "MuzzleShotgun"; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.bulletCount = ((bulletCount > 0) ? ((uint)bulletCount) : 0u); + bulletAttack.procCoefficient = 1f / (float)bulletCount; + bulletAttack.damage = Mathf.LerpUnclamped(minChargeDamageCoefficient, maxChargeDamageCoefficient, num) * damageStat / (float)bulletCount; + bulletAttack.force = Mathf.LerpUnclamped(minChargeForce, maxChargeForce, num); + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + if (num == 1f) + { + bulletAttack.stopperMask = LayerIndex.world.mask; + } + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0f; + bulletAttack.sniper = true; + bulletAttack.Fire(); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.inputBank) + { + inputReleased |= !base.inputBank.skill1.down; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (inputReleased && base.fixedAge >= interruptInterval / attackSpeedStat) + { + return InterruptPriority.Any; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Sniper.SniperWeapon/Reload.cs b/ilspy_dump/ror2_csproj/EntityStates.Sniper.SniperWeapon/Reload.cs new file mode 100644 index 0000000..0ab2a1d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Sniper.SniperWeapon/Reload.cs @@ -0,0 +1,87 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Sniper.SniperWeapon; + +public class Reload : BaseState +{ + public static float baseDuration = 1f; + + public static float reloadTimeFraction = 0.75f; + + public static string soundString = ""; + + private float duration; + + private float reloadTime; + + private Animator modelAnimator; + + private bool reloaded; + + private EntityStateMachine scopeStateMachine; + + private static int PrepBarrageStateHash = Animator.StringToHash("PrepBarrage"); + + private static int PrepBarrageParamHash = Animator.StringToHash("PrepBarrage.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + reloadTime = duration * reloadTimeFraction; + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayAnimation("Gesture", PrepBarrageStateHash, PrepBarrageParamHash, duration); + } + if ((bool)base.skillLocator) + { + GenericSkill secondary = base.skillLocator.secondary; + if ((bool)secondary) + { + scopeStateMachine = secondary.stateMachine; + } + } + if (base.isAuthority && (bool)scopeStateMachine) + { + scopeStateMachine.SetNextState(new LockSkill()); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!reloaded && base.fixedAge >= reloadTime) + { + if ((bool)base.skillLocator) + { + GenericSkill primary = base.skillLocator.primary; + if ((bool)primary) + { + primary.Reset(); + Util.PlaySound(soundString, base.gameObject); + } + } + reloaded = true; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (base.isAuthority && (bool)scopeStateMachine) + { + scopeStateMachine.SetNextStateToMain(); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SpectatorSkills/LockOn.cs b/ilspy_dump/ror2_csproj/EntityStates.SpectatorSkills/LockOn.cs new file mode 100644 index 0000000..7266550 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SpectatorSkills/LockOn.cs @@ -0,0 +1,55 @@ +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; + +namespace EntityStates.SpectatorSkills; + +public class LockOn : BaseSkillState +{ + private Vector3 targetPoint; + + public override void OnEnter() + { + base.OnEnter(); + if (base.inputBank.GetAimRaycast(float.PositiveInfinity, out var hitInfo)) + { + targetPoint = hitInfo.point; + } + else + { + outer.SetNextStateToMain(); + } + RoR2Application.onUpdate += LookAtTarget; + RoR2Application.onLateUpdate += LookAtTarget; + } + + public override void OnExit() + { + RoR2Application.onLateUpdate -= LookAtTarget; + RoR2Application.onUpdate -= LookAtTarget; + base.OnExit(); + } + + public override void Update() + { + base.Update(); + if (base.isAuthority && !IsKeyDownAuthority()) + { + outer.SetNextStateToMain(); + } + } + + private void LookAtTarget() + { + ReadOnlyCollection readOnlyInstancesList = CameraRigController.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + _ = readOnlyInstancesList[i].target == base.gameObject; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Squid.DeathState/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Squid.DeathState/DeathState.cs new file mode 100644 index 0000000..a15e567 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Squid.DeathState/DeathState.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace EntityStates.Squid.DeathState; + +public class DeathState : BaseState +{ + public static float baseDuration; + + private float duration; + + private static int DeathStateHash = Animator.StringToHash("Death"); + + public override void OnEnter() + { + duration = baseDuration; + base.OnEnter(); + PlayAnimation("Body", DeathStateHash); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + if (!outer.destroying && (bool)base.gameObject) + { + EntityState.Destroy(base.gameObject); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Squid.SquidWeapon/FireSpine.cs b/ilspy_dump/ror2_csproj/EntityStates.Squid.SquidWeapon/FireSpine.cs new file mode 100644 index 0000000..df399b4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Squid.SquidWeapon/FireSpine.cs @@ -0,0 +1,117 @@ +using System.Linq; +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Squid.SquidWeapon; + +public class FireSpine : BaseState +{ + public static GameObject hitEffectPrefab; + + public static GameObject muzzleflashEffectPrefab; + + public static float damageCoefficient; + + public static float baseDuration = 2f; + + public static float procCoefficient = 1f; + + public static float forceScalar = 1f; + + private bool hasFiredArrow; + + private ChildLocator childLocator; + + private BullseyeSearch enemyFinder; + + private const float maxVisionDistance = float.PositiveInfinity; + + public bool fullVision = true; + + private float duration; + + private static int FireGooStateHash = Animator.StringToHash("FireGoo"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + GetAimRay(); + PlayAnimation("Gesture", FireGooStateHash); + if (base.isAuthority) + { + FireOrbArrow(); + } + } + + private void FireOrbArrow() + { + if (hasFiredArrow || !NetworkServer.active) + { + return; + } + Ray aimRay = GetAimRay(); + enemyFinder = new BullseyeSearch(); + enemyFinder.viewer = base.characterBody; + enemyFinder.maxDistanceFilter = float.PositiveInfinity; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.sortMode = BullseyeSearch.SortMode.Distance; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + enemyFinder.minDistanceFilter = 0f; + enemyFinder.maxAngleFilter = (fullVision ? 180f : 90f); + enemyFinder.filterByLoS = true; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + enemyFinder.RefreshCandidates(); + HurtBox hurtBox = enemyFinder.GetResults().FirstOrDefault(); + if ((bool)hurtBox) + { + Vector3 vector = hurtBox.transform.position - GetAimRay().origin; + aimRay.origin = GetAimRay().origin; + aimRay.direction = vector; + base.inputBank.aimDirection = vector; + StartAimMode(aimRay); + hasFiredArrow = true; + SquidOrb squidOrb = new SquidOrb(); + squidOrb.forceScalar = forceScalar; + squidOrb.damageValue = base.characterBody.damage * damageCoefficient; + squidOrb.isCrit = Util.CheckRoll(base.characterBody.crit, base.characterBody.master); + squidOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + squidOrb.attacker = base.gameObject; + squidOrb.procCoefficient = procCoefficient; + HurtBox hurtBox2 = hurtBox; + if ((bool)hurtBox2) + { + Transform transform = base.characterBody.modelLocator.modelTransform.GetComponent().FindChild("Muzzle"); + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, "Muzzle", transmit: true); + squidOrb.origin = transform.position; + squidOrb.target = hurtBox2; + OrbManager.instance.AddOrb(squidOrb); + } + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Squid/SquidDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Squid/SquidDeathState.cs new file mode 100644 index 0000000..a4c585c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Squid/SquidDeathState.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace EntityStates.Squid; + +public class SquidDeathState : GenericCharacterDeath +{ + private static int DeathStateHash = Animator.StringToHash("Death"); + + public static float duration = 0f; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", DeathStateHash); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/BaseBatteryPanelState.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/BaseBatteryPanelState.cs new file mode 100644 index 0000000..f6f51c8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/BaseBatteryPanelState.cs @@ -0,0 +1,80 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.SurvivorPod.BatteryPanel; + +public class BaseBatteryPanelState : BaseState +{ + protected struct PodInfo + { + public GameObject podObject; + + public Animator podAnimator; + } + + protected PodInfo podInfo; + + public override void OnEnter() + { + base.OnEnter(); + SetPodObject(base.gameObject.GetComponentInParent()?.gameObject); + } + + private void SetPodObject(GameObject podObject) + { + podInfo = default(PodInfo); + if (!podObject) + { + return; + } + podInfo.podObject = podObject; + ModelLocator component = podObject.GetComponent(); + if ((bool)component) + { + Transform modelTransform = component.modelTransform; + if ((bool)modelTransform) + { + podInfo.podAnimator = modelTransform.GetComponent(); + } + } + } + + protected void PlayPodAnimation(string layerName, string animationStateName, string playbackRateParam, float duration) + { + if ((bool)podInfo.podAnimator) + { + EntityState.PlayAnimationOnAnimator(podInfo.podAnimator, layerName, animationStateName, playbackRateParam, duration); + } + } + + protected void PlayPodAnimation(string layerName, string animationStateName) + { + if ((bool)podInfo.podAnimator) + { + EntityState.PlayAnimationOnAnimator(podInfo.podAnimator, layerName, animationStateName); + } + } + + protected void EnablePickup() + { + ChildLocator component = podInfo.podAnimator.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("BatteryAttachmentPoint"); + if (!transform) + { + return; + } + Transform transform2 = transform.Find("QuestVolatileBatteryWorldPickup(Clone)"); + if ((bool)transform2) + { + GenericPickupController component2 = transform2.GetComponent(); + if ((bool)component2) + { + component2.enabled = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/Opened.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/Opened.cs new file mode 100644 index 0000000..ef9b639 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/Opened.cs @@ -0,0 +1,11 @@ +namespace EntityStates.SurvivorPod.BatteryPanel; + +public class Opened : BaseBatteryPanelState +{ + public override void OnEnter() + { + base.OnEnter(); + PlayPodAnimation("Additive", "OpenPanelFinished"); + EnablePickup(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/Opening.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/Opening.cs new file mode 100644 index 0000000..f6273ac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod.BatteryPanel/Opening.cs @@ -0,0 +1,31 @@ +using RoR2; + +namespace EntityStates.SurvivorPod.BatteryPanel; + +public class Opening : BaseBatteryPanelState +{ + public static float duration; + + public static string openSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayPodAnimation("Additive", "OpenPanel", "OpenPanel.playbackRate", duration); + Util.PlaySound(openSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new Opened()); + } + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Descent.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Descent.cs new file mode 100644 index 0000000..26816a1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Descent.cs @@ -0,0 +1,81 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.SurvivorPod; + +public class Descent : SurvivorPodBaseState +{ + public static float failsafeTimer = 30f; + + private ShakeEmitter shakeEmitter; + + private static int InitialSpawnStateHash = Animator.StringToHash("InitialSpawn"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", InitialSpawnStateHash); + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("Travel"); + if ((bool)transform) + { + shakeEmitter = transform.gameObject.AddComponent(); + shakeEmitter.wave = new Wave + { + amplitude = 1f, + frequency = 180f, + cycleOffset = 0f + }; + shakeEmitter.duration = 10000f; + shakeEmitter.radius = 400f; + shakeEmitter.amplitudeTimeDecay = false; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + protected void AuthorityFixedUpdate() + { + if (base.fixedAge > failsafeTimer) + { + Debug.LogError($"Descent timeout {failsafeTimer}..."); + TransitionIntoNextState(); + return; + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Base"); + if (layerIndex != -1 && modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("Idle")) + { + TransitionIntoNextState(); + } + } + } + + protected virtual void TransitionIntoNextState() + { + outer.SetNextState(new Landed()); + } + + public override void OnExit() + { + EntityState.Destroy(shakeEmitter); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Landed.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Landed.cs new file mode 100644 index 0000000..04f10df --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Landed.cs @@ -0,0 +1,40 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.SurvivorPod; + +public class Landed : SurvivorPodBaseState +{ + private static int IdleStateHash = Animator.StringToHash("Idle"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", IdleStateHash); + Util.PlaySound("Play_UI_podSteamLoop", base.gameObject); + base.vehicleSeat.handleVehicleExitRequestServer.AddCallback(HandleVehicleExitRequest); + } + + public override void FixedUpdate() + { + if (base.fixedAge > 0f) + { + base.survivorPodController.exitAllowed = true; + } + base.FixedUpdate(); + } + + private void HandleVehicleExitRequest(GameObject gameObject, ref bool? result) + { + base.survivorPodController.exitAllowed = false; + outer.SetNextState(new PreRelease()); + result = true; + } + + public override void OnExit() + { + base.vehicleSeat.handleVehicleExitRequestServer.RemoveCallback(HandleVehicleExitRequest); + base.survivorPodController.exitAllowed = false; + Util.PlaySound("Stop_UI_podSteamLoop", base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/PreRelease.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/PreRelease.cs new file mode 100644 index 0000000..2e95f5a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/PreRelease.cs @@ -0,0 +1,40 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.SurvivorPod; + +public class PreRelease : SurvivorPodBaseState +{ + private static int IdleToReleaseStateHash = Animator.StringToHash("IdleToRelease"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", IdleToReleaseStateHash); + Util.PlaySound("Play_UI_podBlastDoorOpen", base.gameObject); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + modelTransform.GetComponent().FindChild("InitialExhaustFX").gameObject.SetActive(value: true); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Base"); + if (layerIndex != -1 && modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("IdleToReleaseFinished")) + { + outer.SetNextState(new Release()); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Release.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Release.cs new file mode 100644 index 0000000..72b381a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/Release.cs @@ -0,0 +1,42 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.SurvivorPod; + +public class Release : SurvivorPodBaseState +{ + public static float ejectionSpeed = 20f; + + private static int ReleaseStateHash = Animator.StringToHash("Release"); + + public static event Action onEnter; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", ReleaseStateHash); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + component.FindChild("Door").gameObject.SetActive(value: false); + component.FindChild("ReleaseExhaustFX").gameObject.SetActive(value: true); + } + Release.onEnter?.Invoke(this, base.vehicleSeat?.currentPassengerBody); + if ((bool)base.survivorPodController && NetworkServer.active && (bool)base.vehicleSeat && (bool)base.vehicleSeat.currentPassengerBody) + { + base.vehicleSeat.EjectPassenger(base.vehicleSeat.currentPassengerBody.gameObject); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (!base.vehicleSeat || !base.vehicleSeat.currentPassengerBody)) + { + outer.SetNextState(new ReleaseFinished()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/ReleaseFinished.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/ReleaseFinished.cs new file mode 100644 index 0000000..be878c1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/ReleaseFinished.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace EntityStates.SurvivorPod; + +public class ReleaseFinished : SurvivorPodBaseState +{ + private static int ReleaseStateHash = Animator.StringToHash("Release"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", ReleaseStateHash); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/SurvivorPodBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/SurvivorPodBaseState.cs new file mode 100644 index 0000000..cdd4422 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.SurvivorPod/SurvivorPodBaseState.cs @@ -0,0 +1,21 @@ +using RoR2; + +namespace EntityStates.SurvivorPod; + +public abstract class SurvivorPodBaseState : EntityState +{ + protected SurvivorPodController survivorPodController { get; private set; } + + protected VehicleSeat vehicleSeat { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + survivorPodController = GetComponent(); + vehicleSeat = survivorPodController?.vehicleSeat; + if (!survivorPodController && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaGeneratorMain.cs b/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaGeneratorMain.cs new file mode 100644 index 0000000..d1d2376 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaGeneratorMain.cs @@ -0,0 +1,105 @@ +using System.Collections.ObjectModel; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.TeleporterHealNovaController; + +public class TeleporterHealNovaGeneratorMain : BaseState +{ + public static GameObject pulsePrefab; + + [SerializeField] + public float minSecondsBetweenPulses; + + private HoldoutZoneController holdoutZone; + + private TeamIndex teamIndex; + + private float previousPulseFraction; + + private int pulseCount; + + private float secondsUntilPulseAvailable; + + public override void OnEnter() + { + base.OnEnter(); + Transform parent = base.transform.parent; + if ((bool)parent) + { + holdoutZone = parent.GetComponentInParent(); + previousPulseFraction = GetCurrentTeleporterChargeFraction(); + } + TeamFilter component = GetComponent(); + teamIndex = (component ? component.teamIndex : TeamIndex.None); + } + + private float GetCurrentTeleporterChargeFraction() + { + return holdoutZone.charge; + } + + public override void FixedUpdate() + { + if (!NetworkServer.active || !(GetDeltaTime() > 0f)) + { + return; + } + if (!holdoutZone || holdoutZone.charge >= 1f) + { + EntityState.Destroy(outer.gameObject); + return; + } + if (secondsUntilPulseAvailable > 0f) + { + secondsUntilPulseAvailable -= GetDeltaTime(); + return; + } + pulseCount = CalculatePulseCount(teamIndex); + float num = CalculateNextPulseFraction(pulseCount, previousPulseFraction); + float currentTeleporterChargeFraction = GetCurrentTeleporterChargeFraction(); + if (num < currentTeleporterChargeFraction) + { + Pulse(); + previousPulseFraction = num; + secondsUntilPulseAvailable = minSecondsBetweenPulses; + } + } + + private static int CalculatePulseCount(TeamIndex teamIndex) + { + int num = 0; + ReadOnlyCollection readOnlyInstancesList = CharacterMaster.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + CharacterMaster characterMaster = readOnlyInstancesList[i]; + if (characterMaster.teamIndex == teamIndex) + { + num += characterMaster.inventory.GetItemCount(RoR2Content.Items.TPHealingNova); + } + } + return num; + } + + private static float CalculateNextPulseFraction(int pulseCount, float previousPulseFraction) + { + float num = 1f / (float)(pulseCount + 1); + for (int i = 1; i <= pulseCount; i++) + { + float num2 = (float)i * num; + if (!(num2 <= previousPulseFraction)) + { + return num2; + } + } + return 1f; + } + + protected void Pulse() + { + GameObject obj = Object.Instantiate(pulsePrefab, base.transform.position, base.transform.rotation, base.transform.parent); + obj.GetComponent().teamIndex = teamIndex; + NetworkServer.Spawn(obj); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaPulse.cs b/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaPulse.cs new file mode 100644 index 0000000..c4020e7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaPulse.cs @@ -0,0 +1,137 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.TeleporterHealNovaController; + +public class TeleporterHealNovaPulse : BaseState +{ + private class HealPulse + { + private readonly List healedTargets = new List(); + + private readonly SphereSearch sphereSearch; + + private float rate; + + private float t; + + private float finalRadius; + + private float healFractionValue; + + private TeamMask teamMask; + + private readonly List hurtBoxesList = new List(); + + public bool isFinished => t >= 1f; + + public HealPulse(Vector3 origin, float finalRadius, float healFractionValue, float duration, TeamIndex teamIndex) + { + sphereSearch = new SphereSearch + { + mask = LayerIndex.entityPrecise.mask, + origin = origin, + queryTriggerInteraction = QueryTriggerInteraction.Collide, + radius = 0f + }; + this.finalRadius = finalRadius; + this.healFractionValue = healFractionValue; + rate = 1f / duration; + teamMask = default(TeamMask); + teamMask.AddTeam(teamIndex); + } + + public void Update(float deltaTime) + { + t += rate * deltaTime; + t = ((t > 1f) ? 1f : t); + sphereSearch.radius = finalRadius * novaRadiusCurve.Evaluate(t); + sphereSearch.RefreshCandidates().FilterCandidatesByHurtBoxTeam(teamMask).FilterCandidatesByDistinctHurtBoxEntities() + .GetHurtBoxes(hurtBoxesList); + int i = 0; + for (int count = hurtBoxesList.Count; i < count; i++) + { + HealthComponent healthComponent = hurtBoxesList[i].healthComponent; + if (!healedTargets.Contains(healthComponent)) + { + healedTargets.Add(healthComponent); + HealTarget(healthComponent); + } + } + hurtBoxesList.Clear(); + } + + private void HealTarget(HealthComponent target) + { + target.HealFraction(healFractionValue, default(ProcChainMask)); + Util.PlaySound("Play_item_proc_TPhealingNova_hitPlayer", target.gameObject); + } + } + + public static AnimationCurve novaRadiusCurve; + + public static float duration; + + private Transform effectTransform; + + private HealPulse healPulse; + + private float radius; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.transform.parent) + { + HoldoutZoneController componentInParent = base.gameObject.GetComponentInParent(); + if ((bool)componentInParent) + { + radius = componentInParent.currentRadius; + } + } + TeamFilter component = GetComponent(); + TeamIndex teamIndex = (component ? component.teamIndex : TeamIndex.None); + if (NetworkServer.active) + { + healPulse = new HealPulse(base.transform.position, radius, 0.5f, duration, teamIndex); + } + effectTransform = base.transform.Find("PulseEffect"); + if ((bool)effectTransform) + { + effectTransform.gameObject.SetActive(value: true); + } + } + + public override void OnExit() + { + if ((bool)effectTransform) + { + effectTransform.gameObject.SetActive(value: false); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + healPulse.Update(GetDeltaTime()); + if (duration < base.fixedAge) + { + EntityState.Destroy(outer.gameObject); + } + } + } + + public override void Update() + { + if ((bool)effectTransform) + { + float num = radius * novaRadiusCurve.Evaluate(base.fixedAge / duration); + effectTransform.localScale = new Vector3(num, num, num); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaWindup.cs b/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaWindup.cs new file mode 100644 index 0000000..7aa0578 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TeleporterHealNovaController/TeleporterHealNovaWindup.cs @@ -0,0 +1,26 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.TeleporterHealNovaController; + +public class TeleporterHealNovaWindup : BaseState +{ + public static GameObject chargeEffectPrefab; + + public static float duration; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleEffect(chargeEffectPrefab, base.transform.position, Quaternion.identity, transmit: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && duration <= base.fixedAge) + { + outer.SetNextState(new TeleporterHealNovaPulse()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TimedChest/Opening.cs b/ilspy_dump/ror2_csproj/EntityStates.TimedChest/Opening.cs new file mode 100644 index 0000000..1f4bdd1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TimedChest/Opening.cs @@ -0,0 +1,47 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.TimedChest; + +public class Opening : BaseState +{ + public static float delayUntilUnlockAchievement; + + private bool hasGrantedAchievement; + + private static int OpeningStateHash = Animator.StringToHash("Opening"); + + public static event Action onOpened; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", OpeningStateHash); + TimedChestController component = GetComponent(); + if ((bool)component) + { + component.purchased = true; + } + if ((bool)base.sfxLocator) + { + Util.PlaySound(base.sfxLocator.openSound, base.gameObject); + } + SetPingable(value: false); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= delayUntilUnlockAchievement && !hasGrantedAchievement) + { + Opening.onOpened?.Invoke(); + hasGrantedAchievement = true; + GenericPickupController componentInChildren = base.gameObject.GetComponentInChildren(); + if ((bool)componentInChildren) + { + componentInChildren.enabled = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/ChargeGoldMegaLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/ChargeGoldMegaLaser.cs new file mode 100644 index 0000000..b849b2c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/ChargeGoldMegaLaser.cs @@ -0,0 +1,14 @@ +namespace EntityStates.TitanMonster; + +public class ChargeGoldMegaLaser : ChargeMegaLaser +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireGoldMegaLaser nextState = new FireGoldMegaLaser(); + outer.SetNextState(nextState); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/ChargeMegaLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/ChargeMegaLaser.cs new file mode 100644 index 0000000..1a09a2f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/ChargeMegaLaser.cs @@ -0,0 +1,224 @@ +using System.Linq; +using RoR2; +using UnityEngine; + +namespace EntityStates.TitanMonster; + +public class ChargeMegaLaser : BaseState +{ + public static float baseDuration = 3f; + + public static float laserMaxWidth = 0.2f; + + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject laserPrefab; + + public static string chargeAttackSoundString; + + public static float lockOnAngle; + + private HurtBox lockedOnHurtBox; + + public float duration; + + private GameObject chargeEffect; + + private GameObject laserEffect; + + private LineRenderer laserLineComponent; + + private Vector3 visualEndPosition; + + private float flashTimer; + + private bool laserOn; + + private BullseyeSearch enemyFinder; + + private const float originalSoundDuration = 2.1f; + + private EffectManagerHelper _emh_chargeEffect; + + private EffectManagerHelper _emh_laserEffect; + + public override void Reset() + { + base.Reset(); + lockedOnHurtBox = null; + duration = 0f; + chargeEffect = null; + laserEffect = null; + laserLineComponent = null; + visualEndPosition = Vector3.zero; + flashTimer = 0f; + laserOn = false; + if (enemyFinder != null) + { + enemyFinder.Reset(); + } + _emh_chargeEffect = null; + _emh_laserEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(chargeAttackSoundString, base.gameObject, 2.1f / duration); + Ray aimRay = GetAimRay(); + enemyFinder = new BullseyeSearch(); + enemyFinder.maxDistanceFilter = 2000f; + enemyFinder.maxAngleFilter = lockOnAngle; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.filterByLoS = false; + enemyFinder.sortMode = BullseyeSearch.SortMode.Angle; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleLaser"); + if ((bool)transform) + { + if ((bool)effectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(effectPrefab)) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(effectPrefab, transform.position, transform.rotation); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)laserPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(laserPrefab)) + { + laserEffect = Object.Instantiate(laserPrefab, transform.position, transform.rotation); + } + else + { + _emh_laserEffect = EffectManager.GetAndActivatePooledEffect(laserPrefab, transform.position, transform.rotation); + laserEffect = _emh_laserEffect.gameObject; + } + laserEffect.transform.parent = transform; + laserLineComponent = laserEffect.GetComponent(); + } + } + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + flashTimer = 0f; + laserOn = true; + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeEffect) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + _emh_chargeEffect = null; + chargeEffect = null; + } + if ((bool)laserEffect) + { + if (_emh_laserEffect != null && _emh_laserEffect.OwningPool != null) + { + _emh_laserEffect.OwningPool.ReturnObject(_emh_laserEffect); + } + else + { + EntityState.Destroy(laserEffect); + } + _emh_laserEffect = null; + laserEffect = null; + } + } + + public override void Update() + { + base.Update(); + if (!laserEffect || !laserLineComponent) + { + return; + } + float num = 1000f; + Ray aimRay = GetAimRay(); + enemyFinder.RefreshCandidates(); + lockedOnHurtBox = enemyFinder.GetResults().FirstOrDefault(); + if ((bool)lockedOnHurtBox) + { + aimRay.direction = lockedOnHurtBox.transform.position - aimRay.origin; + } + Vector3 position = laserEffect.transform.parent.position; + Vector3 point = aimRay.GetPoint(num); + if (Physics.Raycast(aimRay, out var hitInfo, num, (int)LayerIndex.world.mask | (int)LayerIndex.CommonMasks.characterBodiesOrDefault)) + { + point = hitInfo.point; + } + laserLineComponent.SetPosition(0, position); + laserLineComponent.SetPosition(1, point); + float num2; + if (duration - base.age > 0.5f) + { + num2 = base.age / duration; + } + else + { + flashTimer -= Time.deltaTime; + if (flashTimer <= 0f) + { + laserOn = !laserOn; + flashTimer = 1f / 30f; + } + num2 = (laserOn ? 1f : 0f); + } + num2 *= laserMaxWidth; + laserLineComponent.startWidth = num2; + laserLineComponent.endWidth = num2; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + FireMegaLaser nextState = new FireMegaLaser(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/DeathState.cs new file mode 100644 index 0000000..84fb213 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/DeathState.cs @@ -0,0 +1,110 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.TitanMonster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialEffect; + + [SerializeField] + public GameObject deathEffect; + + public static float duration = 2f; + + private float stopwatch; + + private Transform centerTransform; + + private Transform modelBaseTransform; + + private bool attemptedDeathBehavior; + + private EffectData _effectData; + + public override void Reset() + { + base.Reset(); + centerTransform = null; + modelBaseTransform = null; + attemptedDeathBehavior = false; + if (_effectData != null) + { + _effectData.Reset(); + } + } + + public override void OnEnter() + { + base.OnEnter(); + if (!base.modelLocator) + { + return; + } + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + if ((bool)component) + { + centerTransform = component.FindChild("Center"); + if ((bool)initialEffect) + { + if (!EffectManager.ShouldUsePooledEffect(initialEffect)) + { + GameObject obj = Object.Instantiate(initialEffect, centerTransform.position, centerTransform.rotation); + obj.GetComponent().newDuration = duration + 2f; + obj.transform.parent = centerTransform; + } + else + { + EffectManager.GetAndActivatePooledEffect(initialEffect, centerTransform.position, centerTransform.rotation, centerTransform).gameObject.GetComponent().newDuration = duration + 2f; + } + } + } + modelBaseTransform = base.modelLocator.modelBaseTransform; + } + + private void AttemptDeathBehavior() + { + if (attemptedDeathBehavior) + { + return; + } + attemptedDeathBehavior = true; + if ((bool)deathEffect && NetworkServer.active) + { + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.origin = centerTransform.position; + EffectManager.SpawnEffect(deathEffect, _effectData, transmit: true); + } + if ((bool)modelBaseTransform) + { + EntityState.Destroy(modelBaseTransform.gameObject); + modelBaseTransform = null; + } + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } + + public override void FixedUpdate() + { + stopwatch += GetDeltaTime(); + if (stopwatch >= duration) + { + AttemptDeathBehavior(); + } + } + + public override void OnExit() + { + if (!outer.destroying) + { + AttemptDeathBehavior(); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/DeathStateGold.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/DeathStateGold.cs new file mode 100644 index 0000000..96af955 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/DeathStateGold.cs @@ -0,0 +1,5 @@ +namespace EntityStates.TitanMonster; + +public class DeathStateGold : DeathState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireFist.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireFist.cs new file mode 100644 index 0000000..47a0fe2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireFist.cs @@ -0,0 +1,376 @@ +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.TitanMonster; + +public class FireFist : BaseState +{ + private enum SubState + { + Prep, + FireFist, + Exit + } + + private class Predictor + { + private enum ExtrapolationType + { + None, + Linear, + Polar + } + + private Transform bodyTransform; + + private Transform targetTransform; + + private Vector3 targetPosition0; + + private Vector3 targetPosition1; + + private Vector3 targetPosition2; + + private int collectedPositions; + + public bool hasTargetTransform => targetTransform; + + public bool isPredictionReady => collectedPositions > 2; + + public Predictor(Transform bodyTransform) + { + this.bodyTransform = bodyTransform; + } + + private void PushTargetPosition(Vector3 newTargetPosition) + { + targetPosition2 = targetPosition1; + targetPosition1 = targetPosition0; + targetPosition0 = newTargetPosition; + collectedPositions++; + } + + public void SetTargetTransform(Transform newTargetTransform) + { + targetTransform = newTargetTransform; + targetPosition2 = (targetPosition1 = (targetPosition0 = newTargetTransform.position)); + collectedPositions = 1; + } + + public void Update() + { + if ((bool)targetTransform) + { + PushTargetPosition(targetTransform.position); + } + } + + public bool GetPredictedTargetPosition(float time, out Vector3 predictedPosition) + { + Vector3 vector = targetPosition1 - targetPosition2; + Vector3 vector2 = targetPosition0 - targetPosition1; + vector.y = 0f; + vector2.y = 0f; + ExtrapolationType extrapolationType; + if (vector == Vector3.zero || vector2 == Vector3.zero) + { + extrapolationType = ExtrapolationType.None; + } + else + { + Vector3 normalized = vector.normalized; + Vector3 normalized2 = vector2.normalized; + extrapolationType = ((Vector3.Dot(normalized, normalized2) > 0.98f) ? ExtrapolationType.Linear : ExtrapolationType.Polar); + } + float num = 1f / Time.deltaTime; + predictedPosition = targetPosition0; + switch (extrapolationType) + { + case ExtrapolationType.Linear: + predictedPosition = targetPosition0 + vector2 * (time * num); + break; + case ExtrapolationType.Polar: + { + Vector3 position = bodyTransform.position; + Vector3 vector3 = Util.Vector3XZToVector2XY(targetPosition2 - position); + Vector3 vector4 = Util.Vector3XZToVector2XY(targetPosition1 - position); + Vector3 vector5 = Util.Vector3XZToVector2XY(targetPosition0 - position); + float magnitude = vector3.magnitude; + float magnitude2 = vector4.magnitude; + float magnitude3 = vector5.magnitude; + float num2 = Vector2.SignedAngle(vector3, vector4) * num; + float num3 = Vector2.SignedAngle(vector4, vector5) * num; + float num4 = (magnitude2 - magnitude) * num; + float num5 = (magnitude3 - magnitude2) * num; + float num6 = (num2 + num3) * 0.5f; + float num7 = (num4 + num5) * 0.5f; + float num8 = magnitude3 + num7 * time; + if (num8 < 0f) + { + num8 = 0f; + } + Vector2 vector6 = Util.RotateVector2(vector5, num6 * time); + vector6 *= num8 * magnitude3; + predictedPosition = position; + predictedPosition.x += vector6.x; + predictedPosition.z += vector6.y; + break; + } + } + if (Physics.Raycast(new Ray(predictedPosition + Vector3.up * 1f, Vector3.down), out var hitInfo, 200f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + predictedPosition = hitInfo.point; + return true; + } + return false; + } + } + + public static float entryDuration = 1f; + + public static float fireDuration = 2f; + + public static float exitDuration = 1f; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public GameObject fistEffectPrefab; + + [SerializeField] + public GameObject fireEffectPrefab; + + [SerializeField] + public GameObject fistProjectilePrefab; + + public static float maxDistance = 40f; + + public static float trackingDuration = 0.5f; + + public static float fistDamageCoefficient = 2f; + + public static float fistForce = 2000f; + + public static string chargeFistAttackSoundString; + + private bool hasShownPrediction; + + private bool predictionOk; + + protected Vector3 predictedTargetPosition; + + private AimAnimator aimAnimator; + + private GameObject chargeEffect; + + private Transform fistTransform; + + private float stopwatch; + + private EffectData _effectData; + + protected BullseyeSearch enemyFinder; + + private EffectManagerHelper _emh_chargeEffect; + + private SubState subState; + + private Predictor predictor; + + private GameObject predictorDebug; + + private static int FireFistStateHash = Animator.StringToHash("FireFist"); + + public override void Reset() + { + base.Reset(); + hasShownPrediction = false; + predictionOk = false; + predictedTargetPosition = Vector3.zero; + aimAnimator = null; + chargeEffect = null; + fistTransform = null; + stopwatch = 0f; + subState = SubState.Prep; + if (_effectData != null) + { + _effectData.Reset(); + } + if (enemyFinder != null) + { + enemyFinder.Reset(); + } + predictor = null; + predictorDebug = null; + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + if ((bool)base.modelLocator) + { + ChildLocator component = base.modelLocator.modelTransform.GetComponent(); + aimAnimator = base.modelLocator.modelTransform.GetComponent(); + if ((bool)aimAnimator) + { + aimAnimator.enabled = true; + } + if ((bool)component) + { + fistTransform = component.FindChild("RightFist"); + if ((bool)fistTransform) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeEffect = Object.Instantiate(chargeEffectPrefab, fistTransform); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, fistTransform, inResetLocal: true); + chargeEffect = _emh_chargeEffect.gameObject; + } + } + } + } + subState = SubState.Prep; + PlayCrossfade("Body", "PrepFist", "PrepFist.playbackRate", entryDuration, 0.1f); + Util.PlayAttackSpeedSound(chargeFistAttackSoundString, base.gameObject, attackSpeedStat); + if (NetworkServer.active) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + bullseyeSearch.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + bullseyeSearch.maxDistanceFilter = maxDistance; + bullseyeSearch.maxAngleFilter = 90f; + Ray aimRay = GetAimRay(); + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)hurtBox) + { + predictor = new Predictor(base.transform); + predictor.SetTargetTransform(hurtBox.transform); + } + } + } + + protected void DestroyChargeEffect() + { + if ((bool)chargeEffect) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + chargeEffect = null; + _emh_chargeEffect = null; + } + } + + public override void OnExit() + { + base.OnExit(); + DestroyChargeEffect(); + EntityState.Destroy(predictorDebug); + predictorDebug = null; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + switch (subState) + { + case SubState.Prep: + if (predictor != null) + { + predictor.Update(); + } + if (stopwatch <= trackingDuration) + { + if (predictor != null) + { + predictionOk = predictor.GetPredictedTargetPosition(entryDuration - trackingDuration, out predictedTargetPosition); + if (predictionOk && (bool)predictorDebug) + { + predictorDebug.transform.position = predictedTargetPosition; + } + } + } + else if (!hasShownPrediction) + { + hasShownPrediction = true; + PlacePredictedAttack(); + } + if (stopwatch >= entryDuration) + { + predictor = null; + subState = SubState.FireFist; + stopwatch = 0f; + PlayAnimation("Body", FireFistStateHash); + DestroyChargeEffect(); + if (!EffectManager.ShouldUsePooledEffect(fireEffectPrefab)) + { + Object.Instantiate(fireEffectPrefab, fistTransform.position, Quaternion.identity, fistTransform); + } + else + { + EffectManager.GetAndActivatePooledEffect(fireEffectPrefab, fistTransform.position, Quaternion.identity, fistTransform); + } + } + break; + case SubState.FireFist: + if (stopwatch >= fireDuration) + { + subState = SubState.Exit; + stopwatch = 0f; + PlayCrossfade("Body", "ExitFist", "ExitFist.playbackRate", exitDuration, 0.3f); + } + break; + case SubState.Exit: + if (stopwatch >= exitDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + break; + } + } + + protected virtual void PlacePredictedAttack() + { + PlaceSingleDelayBlast(predictedTargetPosition, 0f); + } + + protected void PlaceSingleDelayBlast(Vector3 position, float delay) + { + if (base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = fistProjectilePrefab; + fireProjectileInfo.position = position; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * fistDamageCoefficient; + fireProjectileInfo.force = fistForce; + fireProjectileInfo.crit = base.characterBody.RollCrit(); + fireProjectileInfo.fuseOverride = entryDuration - trackingDuration + delay; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireGoldFist.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireGoldFist.cs new file mode 100644 index 0000000..3035921 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireGoldFist.cs @@ -0,0 +1,31 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.TitanMonster; + +public class FireGoldFist : FireFist +{ + public static int fistCount; + + public static float distanceBetweenFists; + + public static float delayBetweenFists; + + protected override void PlacePredictedAttack() + { + int num = 0; + Vector3 vector = predictedTargetPosition; + Vector3 vector2 = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) * Vector3.forward; + for (int i = -(fistCount / 2); i < fistCount / 2; i++) + { + Vector3 vector3 = vector + vector2 * distanceBetweenFists * i; + float num2 = 60f; + if (Physics.Raycast(new Ray(vector3 + Vector3.up * (num2 / 2f), Vector3.down), out var hitInfo, num2, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + vector3 = hitInfo.point; + } + PlaceSingleDelayBlast(vector3, delayBetweenFists * (float)num); + num++; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireGoldMegaLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireGoldMegaLaser.cs new file mode 100644 index 0000000..cd2e18e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireGoldMegaLaser.cs @@ -0,0 +1,41 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.TitanMonster; + +public class FireGoldMegaLaser : FireMegaLaser +{ + public static GameObject projectilePrefab; + + public static float projectileFireFrequency; + + public static float projectileDamageCoefficient; + + public static float projectileMinSpread; + + public static float projectileMaxSpread; + + private float projectileStopwatch; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + projectileStopwatch += GetDeltaTime() * attackSpeedStat; + if (projectileStopwatch >= 1f / projectileFireFrequency) + { + Ray ray = GetAimRay(); + if ((bool)muzzleTransform) + { + ray.origin = muzzleTransform.transform.position; + } + ray.direction = Util.ApplySpread(ray.direction, projectileMinSpread, projectileMaxSpread, 1f, 1f); + projectileStopwatch -= 1f / projectileFireFrequency; + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damageStat * FireMegaLaser.damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireMegaLaser.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireMegaLaser.cs new file mode 100644 index 0000000..7c6d8a4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/FireMegaLaser.cs @@ -0,0 +1,271 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.TitanMonster; + +public class FireMegaLaser : BaseState +{ + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject laserPrefab; + + public static string playAttackSoundString; + + public static string playLoopSoundString; + + public static string stopLoopSoundString; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float fireFrequency; + + public static float maxDistance; + + public static float minimumDuration; + + public static float maximumDuration; + + public static float lockOnAngle; + + public static float procCoefficientPerTick; + + private HurtBox lockedOnHurtBox; + + private float fireStopwatch; + + private float stopwatch; + + private Ray aimRay; + + private Transform modelTransform; + + private GameObject laserEffect; + + private ChildLocator laserChildLocator; + + private Transform laserEffectEnd; + + protected Transform muzzleTransform; + + private BulletAttack bulletAttack; + + private EffectManagerHelper _emh_laserEffect; + + private BullseyeSearch enemyFinder; + + private bool foundAnyTarget; + + public override void Reset() + { + base.Reset(); + lockedOnHurtBox = null; + modelTransform = null; + laserEffect = null; + laserChildLocator = null; + laserEffectEnd = null; + muzzleTransform = null; + if (bulletAttack != null) + { + bulletAttack.Reset(); + } + if (enemyFinder != null) + { + enemyFinder.Reset(); + } + foundAnyTarget = false; + _emh_laserEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + base.characterBody.SetAimTimer(maximumDuration); + Util.PlaySound(playAttackSoundString, base.gameObject); + Util.PlaySound(playLoopSoundString, base.gameObject); + PlayCrossfade("Gesture, Additive", "FireLaserLoop", 0.25f); + enemyFinder = new BullseyeSearch(); + enemyFinder.viewer = base.characterBody; + enemyFinder.maxDistanceFilter = maxDistance; + enemyFinder.maxAngleFilter = lockOnAngle; + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.filterByLoS = false; + enemyFinder.sortMode = BullseyeSearch.SortMode.Angle; + enemyFinder.teamMaskFilter = TeamMask.allButNeutral; + if ((bool)base.teamComponent) + { + enemyFinder.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex); + } + aimRay = GetAimRay(); + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild("MuzzleLaser"); + if ((bool)muzzleTransform && (bool)laserPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(laserPrefab)) + { + laserEffect = Object.Instantiate(laserPrefab, muzzleTransform.position, muzzleTransform.rotation); + } + else + { + _emh_laserEffect = EffectManager.GetAndActivatePooledEffect(laserPrefab, muzzleTransform.position, muzzleTransform.rotation); + laserEffect = _emh_laserEffect.gameObject; + } + laserEffect.transform.parent = muzzleTransform; + laserChildLocator = laserEffect.GetComponent(); + laserEffectEnd = laserChildLocator.FindChild("LaserEnd"); + } + } + } + UpdateLockOn(); + } + + public override void OnExit() + { + if ((bool)laserEffect) + { + if (_emh_laserEffect != null && _emh_laserEffect.OwningPool != null) + { + _emh_laserEffect.OwningPool.ReturnObject(_emh_laserEffect); + } + else + { + EntityState.Destroy(laserEffect); + } + _emh_laserEffect = null; + laserEffect = null; + } + base.characterBody.SetAimTimer(2f); + Util.PlaySound(stopLoopSoundString, base.gameObject); + PlayCrossfade("Gesture, Additive", "FireLaserEnd", 0.25f); + base.OnExit(); + } + + private void UpdateLockOn() + { + if (base.isAuthority) + { + enemyFinder.searchOrigin = aimRay.origin; + enemyFinder.searchDirection = aimRay.direction; + enemyFinder.RefreshCandidates(); + foundAnyTarget = (lockedOnHurtBox = enemyFinder.GetResults().FirstOrDefault()); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + fireStopwatch += deltaTime; + stopwatch += deltaTime; + aimRay = GetAimRay(); + Vector3 vector = aimRay.origin; + if ((bool)muzzleTransform) + { + vector = muzzleTransform.position; + } + RaycastHit hitInfo; + Vector3 vector2 = (lockedOnHurtBox ? lockedOnHurtBox.transform.position : ((!Util.CharacterRaycast(base.gameObject, aimRay, out hitInfo, maxDistance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore)) ? aimRay.GetPoint(maxDistance) : hitInfo.point)); + Ray ray = new Ray(vector, vector2 - vector); + bool flag = false; + if ((bool)laserEffect && (bool)laserChildLocator) + { + if (Util.CharacterRaycast(base.gameObject, ray, out var hitInfo2, (vector2 - vector).magnitude, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + vector2 = hitInfo2.point; + if (Util.CharacterRaycast(base.gameObject, new Ray(vector2 - ray.direction * 0.1f, -ray.direction), out var _, hitInfo2.distance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.UseGlobal)) + { + vector2 = ray.GetPoint(0.1f); + flag = true; + } + } + laserEffect.transform.rotation = Util.QuaternionSafeLookRotation(vector2 - vector); + laserEffectEnd.transform.position = vector2; + } + if (fireStopwatch > 1f / fireFrequency) + { + string targetMuzzle = "MuzzleLaser"; + if (!flag) + { + FireBullet(modelTransform, ray, targetMuzzle, (vector2 - ray.origin).magnitude + 0.1f); + } + UpdateLockOn(); + fireStopwatch -= 1f / fireFrequency; + } + if (base.isAuthority && (((!base.inputBank || !base.inputBank.skill4.down) && stopwatch > minimumDuration) || stopwatch > maximumDuration)) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + private void FireBullet(Transform modelTransform, Ray aimRay, string targetMuzzle, float maxDistance) + { + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + if (base.isAuthority) + { + if (bulletAttack == null) + { + bulletAttack = new BulletAttack(); + } + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = 1u; + bulletAttack.damage = damageCoefficient * damageStat / fireFrequency; + bulletAttack.force = force; + bulletAttack.muzzleName = targetMuzzle; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.procCoefficient = procCoefficientPerTick; + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0f; + bulletAttack.maxDistance = maxDistance; + bulletAttack.Fire(); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(HurtBoxReference.FromHurtBox(lockedOnHurtBox)); + writer.Write(stopwatch); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + HurtBoxReference hurtBoxReference = reader.ReadHurtBoxReference(); + stopwatch = reader.ReadSingle(); + lockedOnHurtBox = hurtBoxReference.ResolveGameObject()?.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/RechargeRocks.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/RechargeRocks.cs new file mode 100644 index 0000000..7178bce --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/RechargeRocks.cs @@ -0,0 +1,86 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.TitanMonster; + +public class RechargeRocks : BaseState +{ + public static float baseDuration = 3f; + + public static float baseRechargeDuration = 2f; + + public static GameObject effectPrefab; + + public static string attackSoundString; + + public static GameObject rockControllerPrefab; + + private int rocksFired; + + private float duration; + + private float stopwatch; + + private float rechargeStopwatch; + + private GameObject chargeEffect; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + Util.PlaySound(attackSoundString, base.gameObject); + PlayCrossfade("Body", "RechargeRocks", "RechargeRocks.playbackRate", duration, 0.2f); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("LeftFist"); + if ((bool)transform && (bool)effectPrefab) + { + chargeEffect = Object.Instantiate(effectPrefab, transform.position, transform.rotation); + chargeEffect.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffect.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + } + if (NetworkServer.active) + { + GameObject obj = Object.Instantiate(rockControllerPrefab); + obj.GetComponent().SetOwner(base.gameObject); + NetworkServer.Spawn(obj); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeEffect) + { + EntityState.Destroy(chargeEffect); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/SpawnState.cs new file mode 100644 index 0000000..3c845f7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.TitanMonster/SpawnState.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.TitanMonster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static GameObject burrowPrefab; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + ChildLocator component = GetModelTransform().GetComponent(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Transform transform = component.FindChild("BurrowCenter"); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(burrowPrefab)) + { + Object.Instantiate(burrowPrefab, transform.position, Quaternion.identity); + } + else + { + EffectManager.GetAndActivatePooledEffect(burrowPrefab, transform.position, Quaternion.identity); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimGrenade.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimGrenade.cs new file mode 100644 index 0000000..b1aab2f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimGrenade.cs @@ -0,0 +1,10 @@ +namespace EntityStates.Toolbot; + +public abstract class AimGrenade : AimThrowableBase +{ + public override void OnEnter() + { + base.OnEnter(); + detonationRadius = 7f; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimHealDrone.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimHealDrone.cs new file mode 100644 index 0000000..22bf31a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimHealDrone.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Toolbot; + +public class AimHealDrone : AimGrenade +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimStunDrone.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimStunDrone.cs new file mode 100644 index 0000000..9b82897 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/AimStunDrone.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class AimStunDrone : AimGrenade +{ + public static string enterSoundString; + + public static string exitSoundString; + + private static int PrepBombStateHash = Animator.StringToHash("PrepBomb"); + + private static int PutAwayGunStateHash = Animator.StringToHash("PutAwayGun"); + + private static int PrepBombParamHash = Animator.StringToHash("PrepBomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", PrepBombStateHash, PrepBombParamHash, minimumDuration); + PlayAnimation("Stance, Override", PutAwayGunStateHash); + } + + public override void OnExit() + { + base.OnExit(); + outer.SetNextState(new RecoverAimStunDrone()); + Util.PlaySound(exitSoundString, base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseNailgunState.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseNailgunState.cs new file mode 100644 index 0000000..572c04e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseNailgunState.cs @@ -0,0 +1,128 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class BaseNailgunState : BaseToolbotPrimarySkillState +{ + public static float damageCoefficient = 0.1f; + + public static float procCoefficient = 1f; + + public static float force = 100f; + + public static float maxDistance = 50f; + + public new static string muzzleName; + + public static GameObject hitEffectPrefab; + + public static float spreadPitchScale = 0.5f; + + public static float spreadYawScale = 1f; + + public static GameObject tracerEffectPrefab; + + public static string fireSoundString; + + public static GameObject muzzleFlashPrefab; + + public static float spreadBloomValue = 0.2f; + + protected float duration; + + protected int fireNumber; + + private static int FireNailgunStateHash = Animator.StringToHash("FireNailgun"); + + private static int isFiringNailgunStateHash = Animator.StringToHash("isFiringNailgun"); + + private bool _animateNailgunFiring; + + public override string baseMuzzleName => muzzleName; + + protected bool animateNailgunFiring + { + get + { + return _animateNailgunFiring; + } + set + { + if (_animateNailgunFiring != value) + { + _animateNailgunFiring = value; + GetModelAnimator().SetBool(isFiringNailgunStateHash, value); + } + } + } + + protected virtual float GetBaseDuration() + { + return 0f; + } + + public override void OnEnter() + { + base.OnEnter(); + PullCurrentStats(); + } + + protected void PullCurrentStats() + { + attackSpeedStat = base.characterBody.attackSpeed; + critStat = base.characterBody.crit; + duration = GetBaseDuration() / attackSpeedStat; + } + + protected void FireBullet(Ray aimRay, int bulletCount, float spreadPitchScale, float spreadYawScale) + { + fireNumber++; + StartAimMode(aimRay, 3f); + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.aimVector = aimRay.direction; + bulletAttack.origin = aimRay.origin; + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.bulletCount = (uint)bulletCount; + bulletAttack.damage = damageStat * damageCoefficient; + bulletAttack.damageColorIndex = DamageColorIndex.Default; + bulletAttack.damageType = DamageType.Generic; + bulletAttack.falloffModel = BulletAttack.FalloffModel.DefaultBullet; + bulletAttack.force = force; + bulletAttack.HitEffectNormal = false; + bulletAttack.procChainMask = default(ProcChainMask); + bulletAttack.procCoefficient = procCoefficient; + bulletAttack.maxDistance = maxDistance; + bulletAttack.radius = 0f; + bulletAttack.isCrit = RollCrit(); + bulletAttack.muzzleName = ((IToolbotPrimarySkillState)this).muzzleName; + bulletAttack.minSpread = 0f; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.smartCollision = false; + bulletAttack.sniper = false; + bulletAttack.spreadPitchScale = spreadPitchScale * spreadPitchScale; + bulletAttack.spreadYawScale = spreadYawScale * spreadYawScale; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.allowTrajectoryAimAssist = false; + bulletAttack.Fire(); + } + if ((bool)base.characterBody) + { + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + Util.PlaySound(fireSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive", FireNailgunStateHash); + } + else + { + BaseToolbotPrimarySkillStateMethods.PlayGenericFireAnim(this, base.gameObject, base.skillLocator, 0.2f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseToolbotPrimarySkillState.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseToolbotPrimarySkillState.cs new file mode 100644 index 0000000..6843586 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseToolbotPrimarySkillState.cs @@ -0,0 +1,30 @@ +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public abstract class BaseToolbotPrimarySkillState : BaseSkillState, IToolbotPrimarySkillState, ISkillState +{ + public Transform muzzleTransform { get; set; } + + public virtual string baseMuzzleName => "Muzzle"; + + public bool isInDualWield { get; set; } + + public int currentHand { get; set; } + + public string muzzleName { get; set; } + + public SkillDef skillDef { get; set; } + + public override void OnEnter() + { + base.OnEnter(); + BaseToolbotPrimarySkillStateMethods.OnEnter(this, base.gameObject, base.skillLocator, GetModelChildLocator()); + } + + public override void OnExit() + { + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseToolbotPrimarySkillStateMethods.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseToolbotPrimarySkillStateMethods.cs new file mode 100644 index 0000000..324599a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/BaseToolbotPrimarySkillStateMethods.cs @@ -0,0 +1,58 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public static class BaseToolbotPrimarySkillStateMethods +{ + private static int DualWieldFireLStateHash = Animator.StringToHash("DualWieldFire, Left"); + + private static int DualWieldFireRStateHash = Animator.StringToHash("DualWieldFire, Right"); + + public static void OnEnter(T state, GameObject gameObject, SkillLocator skillLocator, ChildLocator modelChildLocator) where T : BaseState, IToolbotPrimarySkillState + { + state.currentHand = 0; + state.isInDualWield = EntityStateMachine.FindByCustomName(gameObject, "Body").state is ToolbotDualWield; + state.muzzleName = state.baseMuzzleName; + state.skillDef = state.activatorSkillSlot.skillDef; + if (state.isInDualWield) + { + if ((object)state.activatorSkillSlot == skillLocator.primary) + { + state.currentHand = -1; + state.muzzleName = "DualWieldMuzzleL"; + } + else if ((object)state.activatorSkillSlot == skillLocator.secondary) + { + state.currentHand = 1; + state.muzzleName = "DualWieldMuzzleR"; + } + } + if (state.muzzleName != null) + { + state.muzzleTransform = modelChildLocator.FindChild(state.muzzleName); + } + } + + public static void PlayGenericFireAnim(T state, GameObject gameObject, SkillLocator skillLocator, float duration) where T : BaseState, IToolbotPrimarySkillState + { + state.currentHand = 0; + if ((object)state.activatorSkillSlot == skillLocator.primary) + { + state.currentHand = -1; + } + else if ((object)state.activatorSkillSlot == skillLocator.secondary) + { + state.currentHand = 1; + } + switch (state.currentHand) + { + case -1: + state.PlayAnimation("Gesture, Additive", DualWieldFireLStateHash); + break; + case 1: + state.PlayAnimation("Gesture, Additive Bonus", DualWieldFireRStateHash); + break; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ChargeSpear.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ChargeSpear.cs new file mode 100644 index 0000000..a85876a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ChargeSpear.cs @@ -0,0 +1,176 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class ChargeSpear : BaseToolbotPrimarySkillState +{ + public static float baseMinChargeDuration; + + public static float baseChargeDuration; + + public static float perfectChargeWindow; + + public static GameObject chargeupVfxPrefab; + + public static GameObject holdChargeVfxPrefab; + + private float minChargeDuration; + + private float chargeDuration; + + private bool released; + + private GameObject chargeupVfxGameObject; + + private GameObject holdChargeVfxGameObject; + + private EffectManagerHelper _emh_chargeupVfx; + + private EffectManagerHelper _emh_holdChargeVfx; + + private static int ChargeSpearStateHash = Animator.StringToHash("ChargeSpear"); + + private static int ChargeSpearParamHash = Animator.StringToHash("ChargeSpear.playbackRate"); + + public override void Reset() + { + base.Reset(); + minChargeDuration = 0f; + chargeDuration = 0f; + released = false; + chargeupVfxGameObject = null; + holdChargeVfxGameObject = null; + _emh_chargeupVfx = null; + _emh_holdChargeVfx = null; + released = false; + } + + public override void OnEnter() + { + base.OnEnter(); + minChargeDuration = baseMinChargeDuration / attackSpeedStat; + chargeDuration = baseChargeDuration / attackSpeedStat; + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive", ChargeSpearStateHash, ChargeSpearParamHash, chargeDuration); + } + if ((bool)base.muzzleTransform) + { + if (!EffectManager.ShouldUsePooledEffect(chargeupVfxPrefab)) + { + chargeupVfxGameObject = Object.Instantiate(chargeupVfxPrefab, base.muzzleTransform); + } + else + { + _emh_chargeupVfx = EffectManager.GetAndActivatePooledEffect(chargeupVfxPrefab, base.muzzleTransform, inResetLocal: true); + chargeupVfxGameObject = _emh_chargeupVfx.gameObject; + } + chargeupVfxGameObject.GetComponent().newDuration = chargeDuration; + } + } + + protected void KillChargeEffect() + { + if (!chargeupVfxGameObject) + { + return; + } + if (!EffectManager.UsePools) + { + EntityState.Destroy(chargeupVfxGameObject); + } + else + { + if (_emh_chargeupVfx != null && _emh_chargeupVfx.OwningPool != null) + { + _emh_chargeupVfx.OwningPool.ReturnObject(_emh_chargeupVfx); + } + else + { + EntityState.Destroy(chargeupVfxGameObject); + } + _emh_chargeupVfx = null; + } + chargeupVfxGameObject = null; + } + + public override void OnExit() + { + KillChargeEffect(); + if ((bool)holdChargeVfxGameObject) + { + if (!EffectManager.UsePools) + { + EntityState.Destroy(holdChargeVfxGameObject); + } + else + { + if (_emh_holdChargeVfx != null && _emh_holdChargeVfx.OwningPool != null) + { + _emh_holdChargeVfx.OwningPool.ReturnObject(_emh_holdChargeVfx); + } + else + { + EntityState.Destroy(holdChargeVfxGameObject); + } + _emh_holdChargeVfx = null; + } + holdChargeVfxGameObject = null; + } + base.OnExit(); + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(base.age / chargeDuration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float num = base.fixedAge - chargeDuration; + if (num >= 0f) + { + _ = perfectChargeWindow; + } + float charge = Mathf.Clamp01(base.fixedAge / chargeDuration); + if (base.fixedAge >= chargeDuration) + { + KillChargeEffect(); + if (!holdChargeVfxGameObject && (bool)base.muzzleTransform) + { + if (!EffectManager.ShouldUsePooledEffect(holdChargeVfxPrefab)) + { + holdChargeVfxGameObject = Object.Instantiate(holdChargeVfxPrefab, base.muzzleTransform); + } + else + { + _emh_holdChargeVfx = EffectManager.GetAndActivatePooledEffect(holdChargeVfxPrefab, base.muzzleTransform, inResetLocal: true); + holdChargeVfxGameObject = _emh_holdChargeVfx.gameObject; + } + } + } + if (base.isAuthority) + { + if (!released && !IsKeyDownAuthority()) + { + released = true; + } + if (released && base.fixedAge >= minChargeDuration) + { + outer.SetNextState(new FireSpear + { + charge = charge, + activatorSkillSlot = base.activatorSkillSlot + }); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/CooldownSpear.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/CooldownSpear.cs new file mode 100644 index 0000000..4362bcd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/CooldownSpear.cs @@ -0,0 +1,56 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class CooldownSpear : BaseToolbotPrimarySkillState +{ + public static float baseDuration; + + public static string enterSoundString; + + private float duration; + + private uint soundID; + + private static int CooldownSpearStateHash = Animator.StringToHash("CooldownSpear"); + + private static int CooldownSpearParamHash = Animator.StringToHash("CooldownSpear.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive", CooldownSpearStateHash, CooldownSpearParamHash, duration); + } + soundID = Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(soundID); + base.OnExit(); + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(1f - base.age / duration, canOnlyIncreaseBloom: false); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHover.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHover.cs new file mode 100644 index 0000000..6521baf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHover.cs @@ -0,0 +1,59 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class DroneProjectileHover : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public int pulseCount = 3; + + [SerializeField] + public float pulseRadius = 7f; + + protected TeamFilter teamFilter; + + protected float interval; + + protected int pulses; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.rigidbody) + { + base.rigidbody.velocity = Vector3.zero; + base.rigidbody.useGravity = false; + } + if (NetworkServer.active && (bool)base.projectileController) + { + teamFilter = base.projectileController.teamFilter; + } + interval = duration / (float)(pulseCount + 1); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + if (base.age >= duration) + { + EntityState.Destroy(base.gameObject); + } + else if (base.age >= interval * (float)(pulses + 1)) + { + pulses++; + Pulse(); + } + } + } + + protected virtual void Pulse() + { + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHoverHeal.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHoverHeal.cs new file mode 100644 index 0000000..d44beb3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHoverHeal.cs @@ -0,0 +1,62 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class DroneProjectileHoverHeal : DroneProjectileHover +{ + public static float healPointsCoefficient; + + public static float healFraction; + + protected override void Pulse() + { + float num = 1f; + ProjectileDamage component = GetComponent(); + if ((bool)component) + { + num = component.damage; + } + HealOccupants(pulseRadius, healPointsCoefficient * num, healFraction); + EffectData effectData = new EffectData(); + effectData.origin = base.transform.position; + effectData.scale = pulseRadius; + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/ExplosionVFX"), effectData, transmit: true); + } + + private static HealthComponent SelectHealthComponent(Collider collider) + { + HurtBox component = collider.GetComponent(); + if ((bool)component && (bool)component.healthComponent) + { + return component.healthComponent; + } + return null; + } + + private void HealOccupants(float radius, float healPoints, float healFraction) + { + Collider[] colliders; + int num = HGPhysics.OverlapSphere(out colliders, base.transform.position, radius, LayerIndex.entityPrecise.mask); + TeamIndex teamIndex = (teamFilter ? teamFilter.teamIndex : TeamIndex.None); + for (int i = 0; i < num; i++) + { + HurtBox component = colliders[i].GetComponent(); + if (!component || !component.healthComponent) + { + continue; + } + HealthComponent healthComponent = component.healthComponent; + if (healthComponent.body.teamComponent.teamIndex == teamIndex) + { + float num2 = healPoints + healthComponent.fullHealth * healFraction; + if (num2 > 0f) + { + healthComponent.Heal(num2, default(ProcChainMask)); + } + } + } + HGPhysics.ReturnResults(colliders); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHoverStun.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHoverStun.cs new file mode 100644 index 0000000..c451400 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileHoverStun.cs @@ -0,0 +1,34 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class DroneProjectileHoverStun : DroneProjectileHover +{ + protected override void Pulse() + { + BlastAttack blastAttack = new BlastAttack + { + baseDamage = 0f, + baseForce = 0f, + attacker = (base.projectileController ? base.projectileController.owner : null), + inflictor = base.gameObject, + bonusForce = Vector3.zero, + attackerFiltering = AttackerFiltering.NeverHitSelf, + crit = false, + damageColorIndex = DamageColorIndex.Default, + damageType = DamageType.Stun1s, + falloffModel = BlastAttack.FalloffModel.None, + procChainMask = default(ProcChainMask), + position = base.transform.position, + procCoefficient = 0f, + teamIndex = (base.projectileController ? base.projectileController.teamFilter.teamIndex : TeamIndex.None), + radius = pulseRadius + }; + blastAttack.Fire(); + EffectData effectData = new EffectData(); + effectData.origin = blastAttack.position; + effectData.scale = blastAttack.radius; + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/ExplosionVFX"), effectData, transmit: true); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileInFlight.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileInFlight.cs new file mode 100644 index 0000000..d5394e9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectileInFlight.cs @@ -0,0 +1,77 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class DroneProjectileInFlight : BaseState +{ + private ProjectileImpactEventCaller impactEventCaller; + + private ProjectileSimple projectileSimple; + + private ProjectileFuse projectileFuse; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + impactEventCaller = GetComponent(); + if ((bool)impactEventCaller) + { + impactEventCaller.impactEvent.AddListener(OnImpact); + } + projectileSimple = GetComponent(); + projectileFuse = GetComponent(); + if ((bool)projectileFuse) + { + projectileFuse.onFuse.AddListener(OnFuse); + } + } + } + + public override void OnExit() + { + if ((bool)impactEventCaller) + { + impactEventCaller.impactEvent.RemoveListener(OnImpact); + } + if ((bool)projectileFuse) + { + projectileFuse.onFuse.RemoveListener(OnFuse); + } + base.OnEnter(); + } + + private void OnImpact(ProjectileImpactInfo projectileImpactInfo) + { + Advance(); + } + + private void OnFuse() + { + Advance(); + } + + private void Advance() + { + if (NetworkServer.active) + { + if ((bool)projectileSimple) + { + projectileSimple.velocity = 0f; + projectileSimple.enabled = false; + } + if ((bool)base.rigidbody) + { + base.rigidbody.velocity = new Vector3(0f, Trajectory.CalculateInitialYSpeedForFlightDuration(DroneProjectilePrepHover.duration), 0f); + } + } + if (base.isAuthority) + { + outer.SetNextState(new DroneProjectilePrepHover()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectilePrepHover.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectilePrepHover.cs new file mode 100644 index 0000000..67998c0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/DroneProjectilePrepHover.cs @@ -0,0 +1,15 @@ +namespace EntityStates.Toolbot; + +public class DroneProjectilePrepHover : BaseState +{ + public static float duration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.age >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireBuzzsaw.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireBuzzsaw.cs new file mode 100644 index 0000000..326146b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireBuzzsaw.cs @@ -0,0 +1,223 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class FireBuzzsaw : BaseToolbotPrimarySkillState +{ + public static float damageCoefficientPerSecond; + + public static float procCoefficientPerSecond = 1f; + + public static string fireSoundString; + + public static string impactSoundString; + + public static string spinUpSoundString; + + public static string spinDownSoundString; + + public static float spreadBloomValue = 0.2f; + + public static float baseFireFrequency; + + public static GameObject spinEffectPrefab; + + public static GameObject spinImpactEffectPrefab; + + public static GameObject impactEffectPrefab; + + public static float selfForceMagnitude; + + private OverlapAttack attack; + + private float fireFrequency; + + private float fireAge; + + private GameObject spinEffectInstance; + + private GameObject spinImpactEffectInstance; + + private bool hitOverlapLastTick; + + protected EffectManagerHelper _emh_spinEffectInstance; + + protected EffectManagerHelper _emh_spinImpactEffectInstance; + + private static int SpinBuzzsawStateHash = Animator.StringToHash("SpinBuzzsaw"); + + private static int EnterBuzzsawStateHash = Animator.StringToHash("EnterBuzzsaw"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int ExitBuzzsawStateHash = Animator.StringToHash("ExitBuzzsaw"); + + private static int ImpactBuzzsawStateHash = Animator.StringToHash("ImpactBuzzsaw"); + + public override string baseMuzzleName => "MuzzleBuzzsaw"; + + public override void Reset() + { + base.Reset(); + if (attack != null) + { + attack.Reset(); + } + fireFrequency = 0f; + fireAge = 0f; + spinEffectInstance = null; + spinImpactEffectInstance = null; + base.muzzleTransform = null; + hitOverlapLastTick = false; + _emh_spinEffectInstance = null; + _emh_spinImpactEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + fireFrequency = baseFireFrequency * attackSpeedStat; + Transform modelTransform = GetModelTransform(); + Util.PlaySound(spinUpSoundString, base.gameObject); + Util.PlaySound(fireSoundString, base.gameObject); + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive Gun", SpinBuzzsawStateHash); + PlayAnimation("Gesture, Additive", EnterBuzzsawStateHash); + } + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = damageCoefficientPerSecond * damageStat / baseFireFrequency; + attack.procCoefficient = procCoefficientPerSecond / baseFireFrequency; + if ((bool)impactEffectPrefab) + { + attack.hitEffectPrefab = impactEffectPrefab; + } + if ((bool)modelTransform) + { + string groupName = "Buzzsaw"; + if (base.isInDualWield) + { + if (base.currentHand == -1) + { + groupName = "BuzzsawL"; + } + else if (base.currentHand == 1) + { + groupName = "BuzzsawR"; + } + } + attack.hitBoxGroup = HitBoxGroup.FindByGroupName(modelTransform.gameObject, groupName); + } + if ((bool)base.muzzleTransform) + { + if ((bool)spinEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(spinEffectPrefab)) + { + spinEffectInstance = Object.Instantiate(spinEffectPrefab, base.muzzleTransform.position, base.muzzleTransform.rotation); + } + else + { + _emh_spinEffectInstance = EffectManager.GetAndActivatePooledEffect(spinEffectPrefab, base.muzzleTransform.position, base.muzzleTransform.rotation); + spinEffectInstance = _emh_spinEffectInstance.gameObject; + } + spinEffectInstance.transform.parent = base.muzzleTransform; + spinEffectInstance.transform.localScale = Vector3.one; + } + if ((bool)spinImpactEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(spinImpactEffectPrefab)) + { + spinImpactEffectInstance = Object.Instantiate(spinImpactEffectPrefab, base.muzzleTransform.position, base.muzzleTransform.rotation); + } + else + { + _emh_spinImpactEffectInstance = EffectManager.GetAndActivatePooledEffect(spinImpactEffectPrefab, base.muzzleTransform.position, base.muzzleTransform.rotation); + spinImpactEffectInstance = _emh_spinImpactEffectInstance.gameObject; + } + spinImpactEffectInstance.transform.parent = base.muzzleTransform; + spinImpactEffectInstance.transform.localScale = Vector3.one; + spinImpactEffectInstance.gameObject.SetActive(value: false); + } + } + attack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + } + + public override void OnExit() + { + base.OnExit(); + Util.PlaySound(spinDownSoundString, base.gameObject); + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive Gun", EmptyStateHash); + PlayAnimation("Gesture, Additive", ExitBuzzsawStateHash); + } + if ((bool)spinEffectInstance) + { + if (!EffectManager.UsePools) + { + EntityState.Destroy(spinEffectInstance); + } + else + { + if (_emh_spinEffectInstance != null && _emh_spinEffectInstance.OwningPool != null) + { + _emh_spinEffectInstance.OwningPool.ReturnObject(_emh_spinEffectInstance); + } + else + { + EntityState.Destroy(spinEffectInstance); + } + _emh_spinEffectInstance = null; + } + } + if ((bool)spinImpactEffectInstance) + { + EntityState.Destroy(spinImpactEffectInstance); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireAge += GetDeltaTime(); + base.characterBody.SetAimTimer(2f); + attackSpeedStat = base.characterBody.attackSpeed; + fireFrequency = baseFireFrequency * attackSpeedStat; + if (fireAge >= 1f / fireFrequency && base.isAuthority) + { + fireAge = 0f; + attack.ResetIgnoredHealthComponents(); + attack.isCrit = base.characterBody.RollCrit(); + hitOverlapLastTick = attack.Fire(); + if (hitOverlapLastTick) + { + Vector3 normalized = (attack.lastFireAverageHitPosition - GetAimRay().origin).normalized; + if ((bool)base.characterMotor) + { + base.characterMotor.ApplyForce(normalized * selfForceMagnitude); + } + Util.PlaySound(impactSoundString, base.gameObject); + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive", ImpactBuzzsawStateHash); + } + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + if (!IsKeyDownAuthority() || (object)base.skillDef != base.activatorSkillSlot.skillDef) + { + outer.SetNextStateToMain(); + } + } + spinImpactEffectInstance.gameObject.SetActive(hitOverlapLastTick); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireGrenadeLauncher.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireGrenadeLauncher.cs new file mode 100644 index 0000000..7eb76b1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireGrenadeLauncher.cs @@ -0,0 +1,70 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class FireGrenadeLauncher : GenericProjectileBaseState, IToolbotPrimarySkillState, ISkillState +{ + private static int FireGrenadeLauncherStateHash = Animator.StringToHash("FireGrenadeLauncher"); + + private static int FireGrenadeLauncherParamHash = Animator.StringToHash("FireGrenadeLauncher.playbackRate"); + + Transform IToolbotPrimarySkillState.muzzleTransform { get; set; } + + string IToolbotPrimarySkillState.baseMuzzleName => targetMuzzle; + + bool IToolbotPrimarySkillState.isInDualWield { get; set; } + + int IToolbotPrimarySkillState.currentHand { get; set; } + + string IToolbotPrimarySkillState.muzzleName { get; set; } + + public SkillDef skillDef { get; set; } + + public GenericSkill activatorSkillSlot { get; set; } + + public override void OnEnter() + { + BaseToolbotPrimarySkillStateMethods.OnEnter(this, base.gameObject, base.skillLocator, GetModelChildLocator()); + base.OnEnter(); + } + + protected override void PlayAnimation(float duration) + { + if (!((IToolbotPrimarySkillState)this).isInDualWield) + { + PlayAnimation("Gesture, Additive", FireGrenadeLauncherStateHash, FireGrenadeLauncherParamHash, duration); + } + else + { + BaseToolbotPrimarySkillStateMethods.PlayGenericFireAnim(this, base.gameObject, base.skillLocator, duration); + } + } + + protected override Ray ModifyProjectileAimRay(Ray projectileRay) + { + if (((IToolbotPrimarySkillState)this).isInDualWield) + { + Transform muzzleTransform = ((IToolbotPrimarySkillState)this).muzzleTransform; + if ((bool)muzzleTransform) + { + projectileRay.origin = muzzleTransform.position; + } + } + return projectileRay; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + this.Serialize(base.skillLocator, writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + this.Deserialize(base.skillLocator, reader); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireNailgun.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireNailgun.cs new file mode 100644 index 0000000..8258f63 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireNailgun.cs @@ -0,0 +1,70 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class FireNailgun : BaseNailgunState +{ + public static float baseRefireInterval; + + public static string spinUpSound; + + private float refireStopwatch; + + private uint loopSoundID; + + private BuffIndex skillsDisabledBuffIndex; + + protected override float GetBaseDuration() + { + return baseRefireInterval; + } + + public override void OnEnter() + { + base.OnEnter(); + loopSoundID = Util.PlaySound(spinUpSound, base.gameObject); + base.animateNailgunFiring = true; + refireStopwatch = duration; + skillsDisabledBuffIndex = DLC2Content.Buffs.DisableAllSkills.buffIndex; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + refireStopwatch += GetDeltaTime(); + if (refireStopwatch >= duration) + { + PullCurrentStats(); + refireStopwatch -= duration; + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, BaseNailgunState.maxDistance, base.gameObject); + Vector3 direction = ray.direction; + Vector3 axis = Vector3.Cross(Vector3.up, direction); + float num = Mathf.Sin((float)fireNumber * 0.5f); + Vector3 vector = Quaternion.AngleAxis(base.characterBody.spreadBloomAngle * num, axis) * direction; + vector = Quaternion.AngleAxis((float)fireNumber * -65.454544f, direction) * vector; + ray.direction = vector; + FireBullet(ray, 1, 0f, 0f); + } + if (base.isAuthority && (!IsKeyDownAuthority() || base.characterBody.isSprinting || base.characterBody.HasBuff(skillsDisabledBuffIndex))) + { + outer.SetNextState(new NailgunSpinDown + { + activatorSkillSlot = base.activatorSkillSlot + }); + } + } + + public override void OnExit() + { + base.animateNailgunFiring = false; + AkSoundEngine.StopPlayingID(loopSoundID); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireSpear.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireSpear.cs new file mode 100644 index 0000000..ad3e641 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/FireSpear.cs @@ -0,0 +1,90 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class FireSpear : GenericBulletBaseState, IToolbotPrimarySkillState, ISkillState +{ + public float charge; + + public static float recoilAmplitude; + + private static int FireSpearStateHash = Animator.StringToHash("FireSpear"); + + private static int FireSpearParamHash = Animator.StringToHash("FireSpear.playbackRate"); + + Transform IToolbotPrimarySkillState.muzzleTransform { get; set; } + + string IToolbotPrimarySkillState.baseMuzzleName => muzzleName; + + bool IToolbotPrimarySkillState.isInDualWield { get; set; } + + int IToolbotPrimarySkillState.currentHand { get; set; } + + string IToolbotPrimarySkillState.muzzleName { get; set; } + + public SkillDef skillDef { get; set; } + + public GenericSkill activatorSkillSlot { get; set; } + + public override void OnEnter() + { + BaseToolbotPrimarySkillStateMethods.OnEnter(this, base.gameObject, base.skillLocator, GetModelChildLocator()); + base.OnEnter(); + } + + protected override void ModifyBullet(BulletAttack bulletAttack) + { + base.ModifyBullet(bulletAttack); + bulletAttack.stopperMask = LayerIndex.world.mask; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.muzzleName = ((IToolbotPrimarySkillState)this).muzzleName; + } + + protected override void FireBullet(Ray aimRay) + { + base.FireBullet(aimRay); + base.characterBody.SetSpreadBloom(1f, canOnlyIncreaseBloom: false); + AddRecoil(-0.6f * recoilAmplitude, -0.8f * recoilAmplitude, -0.1f * recoilAmplitude, 0.1f * recoilAmplitude); + if (!((IToolbotPrimarySkillState)this).isInDualWield) + { + PlayAnimation("Gesture, Additive", FireSpearStateHash, FireSpearParamHash, duration); + } + else + { + BaseToolbotPrimarySkillStateMethods.PlayGenericFireAnim(this, base.gameObject, base.skillLocator, duration); + } + } + + public override void Update() + { + base.Update(); + base.characterBody.SetSpreadBloom(0.9f + base.age / duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new CooldownSpear + { + activatorSkillSlot = activatorSkillSlot + }); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + this.Serialize(base.skillLocator, writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + this.Deserialize(base.skillLocator, reader); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/IToolbotPrimarySkillState.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/IToolbotPrimarySkillState.cs new file mode 100644 index 0000000..32c2c0b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/IToolbotPrimarySkillState.cs @@ -0,0 +1,19 @@ +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public interface IToolbotPrimarySkillState : ISkillState +{ + Transform muzzleTransform { get; set; } + + string muzzleName { get; set; } + + string baseMuzzleName { get; } + + bool isInDualWield { get; set; } + + int currentHand { get; set; } + + SkillDef skillDef { get; set; } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/NailgunFinalBurst.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/NailgunFinalBurst.cs new file mode 100644 index 0000000..f65efd2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/NailgunFinalBurst.cs @@ -0,0 +1,70 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class NailgunFinalBurst : BaseNailgunState +{ + public static int finalBurstBulletCount = 8; + + public static float burstTimeCostCoefficient = 1.2f; + + public static string burstSound; + + public static float selfForce = 1000f; + + private static int FireGrenadeLauncherStateHash = Animator.StringToHash("FireGrenadeLauncher"); + + private static int FireGrenadeLauncherParamHash = Animator.StringToHash("FireGrenadeLauncher.playbackRate"); + + protected override float GetBaseDuration() + { + return (float)finalBurstBulletCount * FireNailgun.baseRefireInterval * burstTimeCostCoefficient; + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody) + { + base.characterBody.SetSpreadBloom(1f, canOnlyIncreaseBloom: false); + } + if (!base.characterBody.HasBuff(DLC2Content.Buffs.DisableAllSkills.buffIndex)) + { + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, BaseNailgunState.maxDistance, base.gameObject); + FireBullet(GetAimRay(), finalBurstBulletCount, BaseNailgunState.spreadPitchScale, BaseNailgunState.spreadYawScale); + if (!base.isInDualWield) + { + PlayAnimation("Gesture, Additive", FireGrenadeLauncherStateHash, FireGrenadeLauncherParamHash, 0.45f / attackSpeedStat); + } + else + { + BaseToolbotPrimarySkillStateMethods.PlayGenericFireAnim(this, base.gameObject, base.skillLocator, 0.45f / attackSpeedStat); + } + Util.PlaySound(burstSound, base.gameObject); + if (base.isAuthority) + { + float num = selfForce * (base.characterMotor.isGrounded ? 0.5f : 1f) * base.characterMotor.mass; + base.characterMotor.ApplyForce(ray.direction * (0f - num)); + } + Util.PlaySound(BaseNailgunState.fireSoundString, base.gameObject); + Util.PlaySound(BaseNailgunState.fireSoundString, base.gameObject); + Util.PlaySound(BaseNailgunState.fireSoundString, base.gameObject); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/NailgunSpinDown.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/NailgunSpinDown.cs new file mode 100644 index 0000000..c9cfbfe --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/NailgunSpinDown.cs @@ -0,0 +1,38 @@ +using RoR2; + +namespace EntityStates.Toolbot; + +public class NailgunSpinDown : BaseNailgunState +{ + public static string spinDownSound; + + public static float baseDuration; + + protected override float GetBaseDuration() + { + return baseDuration; + } + + public override void OnEnter() + { + base.OnEnter(); + Util.PlayAttackSpeedSound(spinDownSound, base.gameObject, attackSpeedStat); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new NailgunFinalBurst + { + activatorSkillSlot = base.activatorSkillSlot + }); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/RecoverAimStunDrone.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/RecoverAimStunDrone.cs new file mode 100644 index 0000000..bf16e3c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/RecoverAimStunDrone.cs @@ -0,0 +1,51 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class RecoverAimStunDrone : BaseState +{ + public static GameObject muzzleEffectPrefab; + + public static string fireSoundString; + + public static float baseDuration; + + private float duration; + + private static int FireBombStateHash = Animator.StringToHash("FireBomb"); + + private static int FireBombParamHash = Animator.StringToHash("FireBomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", FireBombStateHash, FireBombParamHash, duration); + Util.PlaySound(fireSoundString, base.gameObject); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "MuzzleNailgun", transmit: false); + } + } + + public override void OnExit() + { + base.OnExit(); + PlayCrossfade("Stance, Override", "Empty", 0.1f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/StartToolbotStanceSwap.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/StartToolbotStanceSwap.cs new file mode 100644 index 0000000..a102685 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/StartToolbotStanceSwap.cs @@ -0,0 +1,32 @@ +using System.Linq; +using RoR2; + +namespace EntityStates.Toolbot; + +public class StartToolbotStanceSwap : BaseState +{ + private EntityStateMachine stanceStateMachine; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + stanceStateMachine = base.gameObject.GetComponents().FirstOrDefault((EntityStateMachine c) => c.customName == "Stance"); + if (stanceStateMachine?.state is ToolbotStanceBase toolbotStanceBase && toolbotStanceBase.swapStateType != null) + { + stanceStateMachine.SetNextState(new ToolbotStanceSwap + { + previousStanceState = toolbotStanceBase.GetType(), + nextStanceState = toolbotStanceBase.swapStateType + }); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDash.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDash.cs new file mode 100644 index 0000000..a965cc0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDash.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class ToolbotDash : BaseCharacterMain +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float speedMultiplier; + + public static float chargeDamageCoefficient; + + public static float awayForceMagnitude; + + public static float upwardForceMagnitude; + + public static GameObject impactEffectPrefab; + + public static float hitPauseDuration; + + public static string impactSoundString; + + public static float recoilAmplitude; + + public static string startSoundString; + + public static string endSoundString; + + public static GameObject knockbackEffectPrefab; + + public static float knockbackDamageCoefficient; + + public static float massThresholdForKnockback; + + public static float knockbackForce; + + [SerializeField] + public GameObject startEffectPrefab; + + [SerializeField] + public GameObject endEffectPrefab; + + private uint soundID; + + private float duration; + + private float hitPauseTimer; + + private Vector3 idealDirection; + + private OverlapAttack attack; + + private bool inHitPause; + + private List victimsStruck = new List(); + + private static int BoxModeExitStateHash = Animator.StringToHash("BoxModeExit"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int aimWeightStateHash = Animator.StringToHash("aimWeight"); + + private static int BoxModeImpactStateHash = Animator.StringToHash("BoxModeImpact"); + + private static int BoxModeImpactParamHash = Animator.StringToHash("BoxModeImpact.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + if (base.isAuthority) + { + if ((bool)base.inputBank) + { + idealDirection = base.inputBank.aimDirection; + idealDirection.y = 0f; + } + UpdateDirection(); + } + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = true; + } + if ((bool)startEffectPrefab && (bool)base.characterBody) + { + EffectManager.SpawnEffect(startEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: false); + } + if ((bool)base.characterDirection) + { + base.characterDirection.forward = idealDirection; + } + soundID = Util.PlaySound(startSoundString, base.gameObject); + PlayCrossfade("Body", "BoxModeEnter", 0.1f); + PlayCrossfade("Stance, Override", "PutAwayGun", 0.1f); + base.modelAnimator.SetFloat("aimWeight", 0f); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.ArmorBoost); + } + HitBoxGroup hitBoxGroup = null; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Charge"); + } + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = GetTeam(); + attack.damage = chargeDamageCoefficient * damageStat; + attack.hitEffectPrefab = impactEffectPrefab; + attack.forceVector = Vector3.up * upwardForceMagnitude; + attack.pushAwayForce = awayForceMagnitude; + attack.hitBoxGroup = hitBoxGroup; + attack.isCrit = RollCrit(); + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(soundID); + Util.PlaySound(endSoundString, base.gameObject); + if (!outer.destroying && (bool)base.characterBody) + { + if ((bool)endEffectPrefab) + { + EffectManager.SpawnEffect(endEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: false); + } + PlayAnimation("Body", BoxModeExitStateHash); + PlayCrossfade("Stance, Override", EmptyStateHash, 0.1f); + base.characterBody.isSprinting = false; + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.ArmorBoost); + } + } + if ((bool)base.characterMotor && !base.characterMotor.disableAirControlUntilCollision) + { + base.characterMotor.velocity += GetIdealVelocity(); + } + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = false; + } + base.modelAnimator.SetFloat(aimWeightStateHash, 1f); + base.OnExit(); + } + + private float GetDamageBoostFromSpeed() + { + return Mathf.Max(1f, base.characterBody.moveSpeed / base.characterBody.baseMoveSpeed); + } + + private void UpdateDirection() + { + if ((bool)base.inputBank) + { + Vector2 vector = Util.Vector3XZToVector2XY(base.inputBank.moveVector); + if (vector != Vector2.zero) + { + vector.Normalize(); + idealDirection = new Vector3(vector.x, 0f, vector.y).normalized; + } + } + } + + private Vector3 GetIdealVelocity() + { + return base.characterDirection.forward * base.characterBody.moveSpeed * speedMultiplier; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + else + { + if (!base.isAuthority) + { + return; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = true; + } + if ((bool)base.skillLocator.special && base.inputBank.skill4.down) + { + base.skillLocator.special.ExecuteIfReady(); + } + UpdateDirection(); + if (!inHitPause) + { + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = idealDirection; + if ((bool)base.characterMotor && !base.characterMotor.disableAirControlUntilCollision) + { + base.characterMotor.rootMotion += GetIdealVelocity() * GetDeltaTime(); + } + } + attack.damage = damageStat * (chargeDamageCoefficient * GetDamageBoostFromSpeed()); + if (!attack.Fire(victimsStruck)) + { + return; + } + Util.PlaySound(impactSoundString, base.gameObject); + inHitPause = true; + hitPauseTimer = hitPauseDuration; + AddRecoil(-0.5f * recoilAmplitude, -0.5f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + PlayAnimation("Gesture, Additive", BoxModeImpactStateHash, BoxModeImpactParamHash, hitPauseDuration); + for (int i = 0; i < victimsStruck.Count; i++) + { + float num = 0f; + HurtBox hurtBox = victimsStruck[i]; + if (!hurtBox.healthComponent) + { + continue; + } + CharacterMotor component = hurtBox.healthComponent.GetComponent(); + if ((bool)component) + { + num = component.mass; + } + else + { + Rigidbody component2 = hurtBox.healthComponent.GetComponent(); + if ((bool)component2) + { + num = component2.mass; + } + } + if (num >= massThresholdForKnockback) + { + outer.SetNextState(new ToolbotDashImpact + { + victimHealthComponent = hurtBox.healthComponent, + idealDirection = idealDirection, + damageBoostFromSpeed = GetDamageBoostFromSpeed(), + isCrit = attack.isCrit + }); + break; + } + } + } + else + { + base.characterMotor.velocity = Vector3.zero; + hitPauseTimer -= GetDeltaTime(); + if (hitPauseTimer < 0f) + { + inHitPause = false; + } + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDashImpact.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDashImpact.cs new file mode 100644 index 0000000..f463b57 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDashImpact.cs @@ -0,0 +1,71 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class ToolbotDashImpact : BaseState +{ + public HealthComponent victimHealthComponent; + + public Vector3 idealDirection; + + public float damageBoostFromSpeed; + + public bool isCrit; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + if ((bool)victimHealthComponent) + { + DamageInfo damageInfo = new DamageInfo + { + attacker = base.gameObject, + damage = damageStat * ToolbotDash.knockbackDamageCoefficient * damageBoostFromSpeed, + crit = isCrit, + procCoefficient = 1f, + damageColorIndex = DamageColorIndex.Item, + damageType = DamageType.Stun1s, + position = base.characterBody.corePosition + }; + victimHealthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, victimHealthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, victimHealthComponent.gameObject); + } + base.healthComponent.TakeDamageForce(idealDirection * (0f - ToolbotDash.knockbackForce), alwaysApply: true); + } + if (base.isAuthority) + { + AddRecoil(-0.5f * ToolbotDash.recoilAmplitude * 3f, -0.5f * ToolbotDash.recoilAmplitude * 3f, -0.5f * ToolbotDash.recoilAmplitude * 8f, 0.5f * ToolbotDash.recoilAmplitude * 3f); + EffectManager.SimpleImpactEffect(ToolbotDash.knockbackEffectPrefab, base.characterBody.corePosition, base.characterDirection.forward, transmit: true); + outer.SetNextStateToMain(); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(victimHealthComponent ? victimHealthComponent.gameObject : null); + writer.Write(idealDirection); + writer.Write(damageBoostFromSpeed); + writer.Write(isCrit); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + GameObject gameObject = reader.ReadGameObject(); + victimHealthComponent = (gameObject ? gameObject.GetComponent() : null); + idealDirection = reader.ReadVector3(); + damageBoostFromSpeed = reader.ReadSingle(); + isCrit = reader.ReadBoolean(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWield.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWield.cs new file mode 100644 index 0000000..498e06e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWield.cs @@ -0,0 +1,89 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class ToolbotDualWield : ToolbotDualWieldBase +{ + public static string animLayer; + + public static string animStateName; + + public static GameObject coverPrefab; + + public static GameObject coverEjectEffect; + + public static string enterSoundString; + + public static string exitSoundString; + + public static string startLoopSoundString; + + public static string stopLoopSoundString; + + private bool keyReleased; + + private GameObject coverLeftInstance; + + private GameObject coverRightInstance; + + private uint loopSoundID; + + protected override bool shouldAllowPrimarySkills => true; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animLayer, animStateName); + Util.PlaySound(enterSoundString, base.gameObject); + loopSoundID = Util.PlaySound(startLoopSoundString, base.gameObject); + if ((bool)coverPrefab) + { + Transform transform = FindModelChild("LowerArmL"); + Transform transform2 = FindModelChild("LowerArmR"); + if ((bool)transform) + { + coverLeftInstance = Object.Instantiate(coverPrefab, transform.position, transform.rotation, transform); + } + if ((bool)transform2) + { + coverRightInstance = Object.Instantiate(coverPrefab, transform2.position, transform2.rotation, transform2); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + bool flag = this.IsKeyDownAuthority(base.skillLocator, base.inputBank); + keyReleased |= !flag; + if (keyReleased && flag) + { + outer.SetNextState(new ToolbotDualWieldEnd + { + activatorSkillSlot = base.activatorSkillSlot + }); + } + } + } + + public override void OnExit() + { + Util.PlaySound(exitSoundString, base.gameObject); + Util.PlaySound(stopLoopSoundString, base.gameObject); + AkSoundEngine.StopPlayingID(loopSoundID); + if ((bool)coverLeftInstance) + { + EffectManager.SimpleMuzzleFlash(coverEjectEffect, base.gameObject, "LowerArmL", transmit: false); + EntityState.Destroy(coverLeftInstance); + } + if ((bool)coverRightInstance) + { + EffectManager.SimpleMuzzleFlash(coverEjectEffect, base.gameObject, "LowerArmR", transmit: false); + EntityState.Destroy(coverRightInstance); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldBase.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldBase.cs new file mode 100644 index 0000000..2485888 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldBase.cs @@ -0,0 +1,214 @@ +using System; +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public abstract class ToolbotDualWieldBase : GenericCharacterMain, ISkillState +{ + public static BuffDef penaltyBuff; + + public static BuffDef bonusBuff; + + public static SkillDef inertSkillDef; + + public static SkillDef cancelSkillDef; + + public static CharacterCameraParams cameraParams; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public bool applyPenaltyBuff = true; + + [SerializeField] + public bool applyBonusBuff = true; + + [SerializeField] + public bool applyCameraAimMode = true; + + private GenericSkill specialSlot; + + private bool allowPrimarySkills; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private CameraTargetParams.CameraParamsOverrideHandle cameraParamsOverrideHandle; + + private static int isDualWieldingParamHash = Animator.StringToHash("isDualWielding"); + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static GenericSkill.StateMachineResolver offhandStateMachineResolverDelegate = OffhandStateMachineResolver; + + public GenericSkill activatorSkillSlot { get; set; } + + protected GenericSkill primary1Slot { get; private set; } + + protected GenericSkill primary2Slot { get; private set; } + + protected virtual bool shouldAllowPrimarySkills => false; + + public override void OnEnter() + { + base.OnEnter(); + allowPrimarySkills = shouldAllowPrimarySkills; + if (NetworkServer.active && (bool)base.characterBody) + { + if ((bool)penaltyBuff && applyPenaltyBuff) + { + base.characterBody.AddBuff(penaltyBuff); + } + if ((bool)bonusBuff && applyBonusBuff) + { + base.characterBody.AddBuff(bonusBuff); + } + } + if ((bool)base.skillLocator) + { + primary1Slot = base.skillLocator.FindSkillByFamilyName("ToolbotBodyPrimary1"); + primary2Slot = base.skillLocator.FindSkillByFamilyName("ToolbotBodyPrimary2"); + specialSlot = base.skillLocator.FindSkillByFamilyName("ToolbotBodySpecialFamily"); + if (!allowPrimarySkills) + { + if ((object)inertSkillDef != null) + { + if ((bool)base.skillLocator.primary) + { + base.skillLocator.primary.SetSkillOverride(this, inertSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + if ((bool)base.skillLocator.secondary) + { + base.skillLocator.secondary.SetSkillOverride(this, inertSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + } + } + else if ((bool)base.skillLocator.secondary && (bool)primary2Slot) + { + base.skillLocator.secondary.SetSkillOverride(this, primary2Slot.skillDef, GenericSkill.SkillOverridePriority.Contextual); + base.skillLocator.secondary.customStateMachineResolver += offhandStateMachineResolverDelegate; + } + if ((bool)specialSlot && (object)cancelSkillDef != null) + { + specialSlot.SetSkillOverride(this, cancelSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + } + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + if ((bool)base.modelAnimator) + { + base.modelAnimator.SetBool(isDualWieldingParamHash, value: true); + } + if ((bool)base.cameraTargetParams && applyCameraAimMode) + { + cameraParamsOverrideHandle = base.cameraTargetParams.AddParamsOverride(new CameraTargetParams.CameraParamsOverrideRequest + { + cameraParamsData = cameraParams.data, + priority = 1f + }); + } + StopSkills(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(1f); + if (base.isAuthority && (base.characterBody.isSprinting || base.characterBody.HasBuff(DLC2Content.Buffs.DisableAllSkills.buffIndex))) + { + outer.SetNextStateToMain(); + } + } + } + + public override void OnExit() + { + if ((bool)specialSlot && (object)cancelSkillDef != null) + { + specialSlot.UnsetSkillOverride(this, cancelSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + if (!allowPrimarySkills) + { + if ((object)inertSkillDef != null) + { + if ((bool)base.skillLocator.secondary) + { + base.skillLocator.secondary.UnsetSkillOverride(this, inertSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + if ((bool)base.skillLocator.primary) + { + base.skillLocator.primary.UnsetSkillOverride(this, inertSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + } + } + else if ((bool)base.skillLocator.secondary && (bool)primary2Slot) + { + base.skillLocator.secondary.UnsetSkillOverride(this, primary2Slot.skillDef, GenericSkill.SkillOverridePriority.Contextual); + base.skillLocator.secondary.customStateMachineResolver -= offhandStateMachineResolverDelegate; + } + if (NetworkServer.active && (bool)base.characterBody) + { + if ((bool)bonusBuff && applyBonusBuff) + { + base.characterBody.RemoveBuff(bonusBuff); + } + if ((bool)penaltyBuff && applyPenaltyBuff) + { + base.characterBody.RemoveBuff(penaltyBuff); + } + } + crosshairOverrideRequest?.Dispose(); + if ((bool)base.modelAnimator) + { + base.modelAnimator.SetBool(isDualWieldingParamHash, value: false); + } + PlayAnimation("DualWield, Additive", EmptyStateHash); + if ((bool)base.cameraTargetParams && cameraParamsOverrideHandle.isValid) + { + cameraParamsOverrideHandle = base.cameraTargetParams.RemoveParamsOverride(cameraParamsOverrideHandle); + } + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + this.Serialize(base.skillLocator, writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + this.Deserialize(base.skillLocator, reader); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + private static void OffhandStateMachineResolver(GenericSkill genericSkill, SkillDef skillDef, ref EntityStateMachine targetStateMachine) + { + if (string.Equals(skillDef.activationStateMachineName, "Weapon", StringComparison.Ordinal)) + { + targetStateMachine = EntityStateMachine.FindByCustomName(genericSkill.gameObject, "Weapon2"); + } + } + + protected void StopSkills() + { + if (base.isAuthority) + { + EntityStateMachine.FindByCustomName(base.gameObject, "Weapon")?.SetNextStateToMain(); + EntityStateMachine.FindByCustomName(base.gameObject, "Weapon2")?.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldEnd.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldEnd.cs new file mode 100644 index 0000000..25b0831 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldEnd.cs @@ -0,0 +1,40 @@ +using RoR2; + +namespace EntityStates.Toolbot; + +public class ToolbotDualWieldEnd : ToolbotDualWieldBase +{ + public static float baseDuration; + + public static string animLayer; + + public static string animStateName; + + public static string animPlaybackRateParam; + + public static string enterSfx; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animLayer, animStateName, animPlaybackRateParam, duration); + Util.PlaySound(enterSfx, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldStart.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldStart.cs new file mode 100644 index 0000000..9527eac --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotDualWieldStart.cs @@ -0,0 +1,42 @@ +using RoR2; + +namespace EntityStates.Toolbot; + +public class ToolbotDualWieldStart : ToolbotDualWieldBase +{ + public static float baseDuration; + + public static string animLayer; + + public static string animStateName; + + public static string animPlaybackRateParam; + + public static string enterSfx; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animLayer, animStateName, animPlaybackRateParam, duration); + Util.PlaySound(enterSfx, base.gameObject); + if (base.isAuthority && (bool)base.characterMotor && !base.characterMotor.isGrounded) + { + base.characterMotor.disableAirControlUntilCollision = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new ToolbotDualWield + { + activatorSkillSlot = base.activatorSkillSlot + }); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceA.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceA.cs new file mode 100644 index 0000000..17e1004 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceA.cs @@ -0,0 +1,22 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class ToolbotStanceA : ToolbotStanceBase +{ + public override void OnEnter() + { + base.OnEnter(); + swapStateType = typeof(ToolbotStanceB); + if (NetworkServer.active) + { + SetEquipmentSlot(0); + } + } + + protected override GenericSkill GetCurrentPrimarySkill() + { + return GetPrimarySkill1(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceB.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceB.cs new file mode 100644 index 0000000..5809c93 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceB.cs @@ -0,0 +1,22 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class ToolbotStanceB : ToolbotStanceBase +{ + public override void OnEnter() + { + base.OnEnter(); + swapStateType = typeof(ToolbotStanceA); + if (NetworkServer.active) + { + SetEquipmentSlot(1); + } + } + + protected override GenericSkill GetCurrentPrimarySkill() + { + return GetPrimarySkill2(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceBase.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceBase.cs new file mode 100644 index 0000000..28df1d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceBase.cs @@ -0,0 +1,124 @@ +using System; +using RoR2; +using RoR2.Skills; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Toolbot; + +public class ToolbotStanceBase : BaseState +{ + protected enum WeaponStance + { + None = -1, + Nailgun, + Spear, + Grenade, + Buzzsaw + } + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + public static GameObject emptyCrosshairPrefab; + + public static AnimationCurve emptyCrosshairSpreadCurve; + + protected Inventory inventory; + + public Type swapStateType; + + protected void SetPrimarySkill() + { + base.skillLocator.primary = GetCurrentPrimarySkill(); + } + + protected void SetSecondarySkill(string skillName) + { + if ((bool)base.skillLocator) + { + base.skillLocator.secondary = base.skillLocator.FindSkill(skillName); + } + } + + protected string GetSkillSlotStance(GenericSkill skillSlot) + { + return (skillSlot.skillDef as ToolbotWeaponSkillDef)?.stanceName ?? string.Empty; + } + + protected GenericSkill GetPrimarySkill1() + { + return base.skillLocator.FindSkillByFamilyName("ToolbotBodyPrimary1"); + } + + protected GenericSkill GetPrimarySkill2() + { + return base.skillLocator.FindSkillByFamilyName("ToolbotBodyPrimary2"); + } + + protected virtual GenericSkill GetCurrentPrimarySkill() + { + return null; + } + + protected void UpdateCrosshairParameters(ToolbotWeaponSkillDef weaponSkillDef) + { + GameObject crosshairPrefab = emptyCrosshairPrefab; + AnimationCurve crosshairSpreadCurve = emptyCrosshairSpreadCurve; + if ((bool)weaponSkillDef) + { + crosshairPrefab = weaponSkillDef.crosshairPrefab; + crosshairSpreadCurve = weaponSkillDef.crosshairSpreadCurve; + } + crosshairOverrideRequest?.Dispose(); + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairPrefab, CrosshairUtils.OverridePriority.Skill); + base.characterBody.spreadBloomCurve = crosshairSpreadCurve; + } + + protected void SetEquipmentSlot(byte i) + { + if ((bool)inventory) + { + inventory.SetActiveEquipmentSlot(i); + } + } + + public override void OnEnter() + { + base.OnEnter(); + inventory = (base.characterBody ? base.characterBody.inventory : null); + SetPrimarySkill(); + ToolbotWeaponSkillDef toolbotWeaponSkillDef = GetCurrentPrimarySkill()?.skillDef as ToolbotWeaponSkillDef; + if ((bool)toolbotWeaponSkillDef) + { + SendWeaponStanceToAnimator(toolbotWeaponSkillDef); + PlayCrossfade("Gesture, Additive", toolbotWeaponSkillDef.enterGestureAnimState, 0.2f); + } + UpdateCrosshairParameters(toolbotWeaponSkillDef); + } + + public override void OnExit() + { + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + protected void SendWeaponStanceToAnimator(ToolbotWeaponSkillDef weaponSkillDef) + { + if ((bool)weaponSkillDef) + { + GetModelAnimator().SetInteger("weaponStance", weaponSkillDef.animatorWeaponIndex); + } + } + + protected static WeaponStance GetSkillStance(GenericSkill skillSlot) + { + return (skillSlot?.skillDef as ToolbotWeaponSkillDef)?.stanceName switch + { + "Nailgun" => WeaponStance.Nailgun, + "Spear" => WeaponStance.Spear, + "Grenade" => WeaponStance.Grenade, + "Buzzsaw" => WeaponStance.Buzzsaw, + _ => WeaponStance.None, + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceSwap.cs b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceSwap.cs new file mode 100644 index 0000000..50794a3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Toolbot/ToolbotStanceSwap.cs @@ -0,0 +1,69 @@ +using System; +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Toolbot; + +public class ToolbotStanceSwap : ToolbotStanceBase +{ + [SerializeField] + private float baseDuration = 0.5f; + + private Run.FixedTimeStamp endTime; + + public Type nextStanceState; + + public Type previousStanceState; + + public override void OnEnter() + { + base.OnEnter(); + float num = baseDuration / attackSpeedStat; + endTime = Run.FixedTimeStamp.now + num; + GenericSkill a = GetPrimarySkill1(); + GenericSkill b = GetPrimarySkill2(); + if (previousStanceState != typeof(ToolbotStanceA)) + { + Util.Swap(ref a, ref b); + } + if ((bool)b && b.skillDef is ToolbotWeaponSkillDef toolbotWeaponSkillDef) + { + SendWeaponStanceToAnimator(toolbotWeaponSkillDef); + Util.PlaySound(toolbotWeaponSkillDef.entrySound, base.gameObject); + } + if ((bool)a && a.skillDef is ToolbotWeaponSkillDef toolbotWeaponSkillDef2) + { + PlayAnimation("Stance, Additive", toolbotWeaponSkillDef2.exitAnimState, "StanceSwap.playbackRate", num * 0.5f); + PlayAnimation("Gesture, Additive", toolbotWeaponSkillDef2.exitGestureAnimState); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && endTime.hasPassed) + { + outer.SetNextState(EntityStateCatalog.InstantiateState(nextStanceState)); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + EntityStateIndex stateIndex = EntityStateCatalog.GetStateIndex(previousStanceState); + EntityStateIndex stateIndex2 = EntityStateCatalog.GetStateIndex(nextStanceState); + writer.Write(stateIndex); + writer.Write(stateIndex2); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + EntityStateIndex entityStateIndex = reader.ReadEntityStateIndex(); + EntityStateIndex entityStateIndex2 = reader.ReadEntityStateIndex(); + previousStanceState = EntityStateCatalog.GetStateType(entityStateIndex); + nextStanceState = EntityStateCatalog.GetStateType(entityStateIndex2); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.TreebotFlower/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.TreebotFlower/SpawnState.cs new file mode 100644 index 0000000..0213354 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.TreebotFlower/SpawnState.cs @@ -0,0 +1,31 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot.TreebotFlower; + +public class SpawnState : BaseState +{ + public static float duration; + + public static string enterSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Base", SpawnStateHash, SpawnParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new TreebotFlower2Projectile()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.TreebotFlower/TreebotFlower2Projectile.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.TreebotFlower/TreebotFlower2Projectile.cs new file mode 100644 index 0000000..5c11126 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.TreebotFlower/TreebotFlower2Projectile.cs @@ -0,0 +1,221 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Orbs; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Treebot.TreebotFlower; + +public class TreebotFlower2Projectile : BaseState +{ + public static float yankIdealDistance; + + public static AnimationCurve yankSuitabilityCurve; + + public static float healthFractionYieldPerHit; + + public static float radius; + + public static float healPulseCount; + + public static float duration; + + public static float rootPulseCount; + + public static string enterSoundString; + + public static string exitSoundString; + + public static GameObject enterEffectPrefab; + + public static GameObject exitEffectPrefab; + + private List rootedBodies; + + private float healTimer; + + private float rootPulseTimer; + + private GameObject owner; + + private ProcChainMask procChainMask; + + private float procCoefficient; + + private TeamIndex teamIndex = TeamIndex.None; + + private float damage; + + private DamageTypeCombo damageType; + + private bool crit; + + private float healPulseHealthFractionValue; + + private static int SpawnToIdleStateHash = Animator.StringToHash("SpawnToIdle"); + + public override void OnEnter() + { + base.OnEnter(); + ProjectileController component = GetComponent(); + if ((bool)component) + { + owner = component.owner; + procChainMask = component.procChainMask; + procCoefficient = component.procCoefficient; + teamIndex = component.teamFilter.teamIndex; + } + ProjectileDamage component2 = GetComponent(); + if ((bool)component2) + { + damage = component2.damage; + damageType = component2.damageType; + crit = component2.crit; + } + if (NetworkServer.active) + { + rootedBodies = new List(); + } + PlayAnimation("Base", SpawnToIdleStateHash); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)enterEffectPrefab) + { + EffectManager.SimpleEffect(enterEffectPrefab, base.transform.position, base.transform.rotation, transmit: false); + } + ChildLocator component3 = GetModelTransform().GetComponent(); + if ((bool)component3) + { + Transform obj = component3.FindChild("AreaIndicator"); + obj.localScale = new Vector3(radius, radius, radius); + obj.gameObject.SetActive(value: true); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + float deltaTime = GetDeltaTime(); + rootPulseTimer -= deltaTime; + healTimer -= deltaTime; + if (rootPulseTimer <= 0f) + { + rootPulseTimer += duration / rootPulseCount; + RootPulse(); + } + if (healTimer <= 0f) + { + healTimer += duration / healPulseCount; + HealPulse(); + } + if (base.fixedAge >= duration) + { + EntityState.Destroy(base.gameObject); + } + } + } + + private void RootPulse() + { + Vector3 position = base.transform.position; + HurtBox[] hurtBoxes = new SphereSearch + { + origin = position, + radius = radius, + mask = LayerIndex.entityPrecise.mask + }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(teamIndex)).OrderCandidatesByDistance() + .FilterCandidatesByDistinctHurtBoxEntities() + .GetHurtBoxes(); + foreach (HurtBox hurtBox in hurtBoxes) + { + CharacterBody body = hurtBox.healthComponent.body; + if (!rootedBodies.Contains(body)) + { + rootedBodies.Add(body); + body.AddBuff(RoR2Content.Buffs.Entangle); + body.RecalculateStats(); + Vector3 vector = hurtBox.transform.position - position; + float magnitude = vector.magnitude; + Vector3 vector2 = vector / magnitude; + Rigidbody component = hurtBox.healthComponent.GetComponent(); + float num = (component ? component.mass : 1f); + float num2 = magnitude - yankIdealDistance; + float num3 = yankSuitabilityCurve.Evaluate(num); + Vector3 vector3 = (component ? component.velocity : Vector3.zero); + if (HGMath.IsVectorNaN(vector3)) + { + vector3 = Vector3.zero; + } + Vector3 vector4 = -vector3; + if (num2 > 0f) + { + vector4 = vector2 * (0f - Trajectory.CalculateInitialYSpeedForHeight(num2, 0f - body.acceleration)); + } + Vector3 force = vector4 * (num * num3); + DamageInfo damageInfo = new DamageInfo + { + attacker = owner, + inflictor = base.gameObject, + crit = crit, + damage = damage, + damageColorIndex = DamageColorIndex.Default, + damageType = damageType, + force = force, + position = hurtBox.transform.position, + procChainMask = procChainMask, + procCoefficient = procCoefficient + }; + hurtBox.healthComponent.TakeDamage(damageInfo); + HurtBox hurtBoxReference = hurtBox; + HurtBoxGroup hurtBoxGroup = hurtBox.hurtBoxGroup; + for (int j = 0; (float)j < Mathf.Min(4f, body.radius * 2f); j++) + { + EffectData effectData = new EffectData + { + scale = 1f, + origin = position, + genericFloat = Mathf.Max(0.2f, duration - base.fixedAge) + }; + effectData.SetHurtBoxReference(hurtBoxReference); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/OrbEffects/EntangleOrbEffect"), effectData, transmit: true); + hurtBoxReference = hurtBoxGroup.hurtBoxes[Random.Range(0, hurtBoxGroup.hurtBoxes.Length)]; + } + } + } + } + + public override void OnExit() + { + if (rootedBodies != null) + { + foreach (CharacterBody rootedBody in rootedBodies) + { + rootedBody.RemoveBuff(RoR2Content.Buffs.Entangle); + } + rootedBodies = null; + } + Util.PlaySound(exitSoundString, base.gameObject); + if ((bool)exitEffectPrefab) + { + EffectManager.SimpleEffect(exitEffectPrefab, base.transform.position, base.transform.rotation, transmit: false); + } + base.OnExit(); + } + + private void HealPulse() + { + HealthComponent healthComponent = (owner ? owner.GetComponent() : null); + if ((bool)healthComponent && rootedBodies.Count > 0) + { + float num = 1f / healPulseCount; + HealOrb healOrb = new HealOrb(); + healOrb.origin = base.transform.position; + healOrb.target = healthComponent.body.mainHurtBox; + healOrb.healValue = num * healthFractionYieldPerHit * healthComponent.fullHealth * (float)rootedBodies.Count; + healOrb.overrideDuration = 0.3f; + OrbManager.instance.AddOrb(healOrb); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.UnlockInteractable/Unlock.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.UnlockInteractable/Unlock.cs new file mode 100644 index 0000000..79b4720 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.UnlockInteractable/Unlock.cs @@ -0,0 +1,25 @@ +using System; +using RoR2; +using RoR2.Mecanim; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Treebot.UnlockInteractable; + +public class Unlock : BaseState +{ + private static int ReviveParamHash = Animator.StringToHash("Revive"); + + public static event Action onActivated; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active) + { + Unlock.onActivated?.Invoke(GetComponent().lastActivator); + } + GetModelAnimator().SetBool(ReviveParamHash, value: true); + GetModelTransform().GetComponent().enabled = true; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimFlower.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimFlower.cs new file mode 100644 index 0000000..6b591a8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimFlower.cs @@ -0,0 +1,47 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot.Weapon; + +public class AimFlower : AimThrowableBase +{ + public static float healthCostFraction; + + private bool keyDown = true; + + public override void Update() + { + base.Update(); + keyDown &= !base.inputBank.skill1.down; + } + + protected override bool KeyIsDown() + { + return keyDown; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + protected override void FireProjectile() + { + if ((bool)base.healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + base.FireProjectile(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortar.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortar.cs new file mode 100644 index 0000000..c36f356 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortar.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot.Weapon; + +public class AimMortar : AimThrowableBase +{ + public static string enterSoundString; + + public static string exitSoundString; + + private static int StateHash = Animator.StringToHash(""); + + private static int ParamHash = Animator.StringToHash(".playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", StateHash, ParamHash, minimumDuration); + } + + public override void OnExit() + { + base.OnExit(); + outer.SetNextState(new FireMortar()); + if (!outer.destroying) + { + Util.PlaySound(exitSoundString, base.gameObject); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortar2.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortar2.cs new file mode 100644 index 0000000..2b6438e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortar2.cs @@ -0,0 +1,65 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Treebot.Weapon; + +public class AimMortar2 : AimThrowableBase +{ + [SerializeField] + public float healthCostFraction; + + public static string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public string fireSound; + + [SerializeField] + public string enterSound; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Gesture, Additive", "PrepBomb", 0.1f); + Util.PlaySound(enterSound, base.gameObject); + } + + protected override void OnProjectileFiredLocal() + { + if (NetworkServer.active && (bool)base.healthComponent && healthCostFraction >= Mathf.Epsilon) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + Util.PlaySound(fireSound, base.gameObject); + PlayCrossfade("Gesture, Additive", "FireBomb", 0.1f); + } + + protected override bool KeyIsDown() + { + return base.inputBank.skill2.down; + } + + protected override void ModifyProjectile(ref FireProjectileInfo fireProjectileInfo) + { + base.ModifyProjectile(ref fireProjectileInfo); + fireProjectileInfo.position = currentTrajectoryInfo.hitPoint; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.speedOverride = 0f; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortarRain.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortarRain.cs new file mode 100644 index 0000000..e910c42 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/AimMortarRain.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Treebot.Weapon; + +public class AimMortarRain : AimMortar2 +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/ChargePlantSonicBoom.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/ChargePlantSonicBoom.cs new file mode 100644 index 0000000..425fdbd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/ChargePlantSonicBoom.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Treebot.Weapon; + +public class ChargePlantSonicBoom : ChargeSonicBoom +{ + protected override EntityState GetNextState() + { + return new FirePlantSonicBoom(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/ChargeSonicBoom.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/ChargeSonicBoom.cs new file mode 100644 index 0000000..f339780 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/ChargeSonicBoom.cs @@ -0,0 +1,95 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot.Weapon; + +public class ChargeSonicBoom : BaseState +{ + [SerializeField] + public string sound; + + [SerializeField] + public GameObject chargeEffectPrefab; + + public static string muzzleName; + + public static float baseDuration; + + private float duration; + + private GameObject chargeEffect; + + private EffectManagerHelper _emh_chargeEffect; + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffect = null; + _emh_chargeEffect = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(sound, base.gameObject); + base.characterBody.SetAimTimer(3f); + if (!chargeEffectPrefab) + { + return; + } + Transform transform = FindModelChild(muzzleName); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeEffect = Object.Instantiate(chargeEffectPrefab, transform); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform, inResetLocal: true); + chargeEffect = _emh_chargeEffect.gameObject; + } + chargeEffect.transform.localPosition = Vector3.zero; + chargeEffect.transform.localRotation = Quaternion.identity; + } + } + + public override void OnExit() + { + if ((bool)chargeEffect) + { + if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffect); + } + chargeEffect = null; + _emh_chargeEffect = null; + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(GetNextState()); + } + } + + protected virtual EntityState GetNextState() + { + return new FireSonicBoom(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/CreatePounder.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/CreatePounder.cs new file mode 100644 index 0000000..5ce6b8c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/CreatePounder.cs @@ -0,0 +1,150 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.UI; +using UnityEngine; + +namespace EntityStates.Treebot.Weapon; + +public class CreatePounder : BaseState +{ + public static float baseDuration; + + public static GameObject areaIndicatorPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient; + + public static GameObject muzzleflashEffect; + + public static GameObject goodCrosshairPrefab; + + public static GameObject badCrosshairPrefab; + + public static string prepSoundString; + + public static float maxDistance; + + public static string fireSoundString; + + public static float maxSlopeAngle; + + private float duration; + + private float stopwatch; + + private bool goodPlacement; + + private GameObject areaIndicatorInstance; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private EffectManagerHelper _emh_areaIndicatorInstance; + + private static int PrepWallStateHash = Animator.StringToHash("PrepWall"); + + private static int PrepWallParamHash = Animator.StringToHash("PrepWall.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + stopwatch = 0f; + goodPlacement = false; + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", PrepWallStateHash, PrepWallParamHash, duration); + Util.PlaySound(prepSoundString, base.gameObject); + if (!EffectManager.ShouldUsePooledEffect(areaIndicatorPrefab)) + { + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab); + } + else + { + _emh_areaIndicatorInstance = EffectManager.GetAndActivatePooledEffect(areaIndicatorPrefab, Vector3.zero, Quaternion.identity); + areaIndicatorInstance = _emh_areaIndicatorInstance.gameObject; + } + UpdateAreaIndicator(); + } + + private void UpdateAreaIndicator() + { + bool flag = goodPlacement; + goodPlacement = false; + areaIndicatorInstance.SetActive(value: true); + if ((bool)areaIndicatorInstance) + { + float num = maxDistance; + float extraRaycastDistance = 0f; + if (Physics.Raycast(CameraRigController.ModifyAimRayIfApplicable(GetAimRay(), base.gameObject, out extraRaycastDistance), out var hitInfo, num + extraRaycastDistance, LayerIndex.world.mask)) + { + areaIndicatorInstance.transform.position = hitInfo.point; + areaIndicatorInstance.transform.up = hitInfo.normal; + goodPlacement = Vector3.Angle(Vector3.up, hitInfo.normal) < maxSlopeAngle; + } + if (flag != goodPlacement || crosshairOverrideRequest == null) + { + crosshairOverrideRequest?.Dispose(); + GameObject crosshairPrefab = (goodPlacement ? goodCrosshairPrefab : badCrosshairPrefab); + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairPrefab, CrosshairUtils.OverridePriority.Skill); + } + } + areaIndicatorInstance.SetActive(goodPlacement); + } + + public override void Update() + { + base.Update(); + UpdateAreaIndicator(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && !base.inputBank.skill4.down && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (goodPlacement) + { + Util.PlaySound(fireSoundString, base.gameObject); + if ((bool)areaIndicatorInstance && base.isAuthority) + { + bool crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(projectilePrefab, areaIndicatorInstance.transform.position, Quaternion.identity, base.gameObject, damageStat * damageCoefficient, 0f, crit); + } + } + else + { + base.skillLocator.special.AddOneStock(); + } + if (_emh_areaIndicatorInstance != null && _emh_areaIndicatorInstance.OwningPool != null) + { + _emh_areaIndicatorInstance.OwningPool.ReturnObject(_emh_areaIndicatorInstance); + } + else + { + EntityState.Destroy(areaIndicatorInstance.gameObject); + } + areaIndicatorInstance = null; + _emh_areaIndicatorInstance = null; + crosshairOverrideRequest?.Dispose(); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireMortar.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireMortar.cs new file mode 100644 index 0000000..6cbaac4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireMortar.cs @@ -0,0 +1,45 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot.Weapon; + +public class FireMortar : BaseState +{ + public static GameObject muzzleEffectPrefab; + + public static string fireSoundString; + + public static float baseDuration; + + private float duration; + + private static int FireBombStateHash = Animator.StringToHash("FireBomb"); + + private static int FireBombParamHash = Animator.StringToHash("FireBomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", FireBombStateHash, FireBombParamHash, duration); + Util.PlaySound(fireSoundString, base.gameObject); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "MuzzleNailgun", transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireMortar2.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireMortar2.cs new file mode 100644 index 0000000..fd6edde --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireMortar2.cs @@ -0,0 +1,91 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Treebot.Weapon; + +public class FireMortar2 : BaseState +{ + public static float baseDuration; + + public static GameObject projectilePrefab; + + public static string fireSound; + + public static float maxDistance; + + public static float damageCoefficient; + + public static float force; + + public static string muzzleName; + + public static GameObject muzzleEffect; + + public static float healthCostFraction; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + EffectManager.SimpleMuzzleFlash(muzzleEffect, base.gameObject, muzzleName, transmit: false); + Util.PlaySound(fireSound, base.gameObject); + PlayCrossfade("Gesture, Additive", "FireBomb", 0.1f); + if (base.isAuthority) + { + Fire(); + } + if (NetworkServer.active && (bool)base.healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal | DamageType.BypassArmor; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + private void Fire() + { + RaycastHit hitInfo; + Vector3 position = ((!base.inputBank.GetAimRaycast(maxDistance, out hitInfo)) ? base.inputBank.GetAimRay().GetPoint(maxDistance) : hitInfo.point); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = position; + fireProjectileInfo.rotation = Quaternion.identity; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageCoefficient * damageStat; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.target = null; + fireProjectileInfo.speedOverride = 0f; + fireProjectileInfo.fuseOverride = -1f; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FirePlantSonicBoom.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FirePlantSonicBoom.cs new file mode 100644 index 0000000..6309d57 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FirePlantSonicBoom.cs @@ -0,0 +1,73 @@ +using RoR2; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Treebot.Weapon; + +public class FirePlantSonicBoom : FireSonicBoom +{ + public static float damageCoefficient; + + public static float procCoefficient; + + public static GameObject hitEffectPrefab; + + public static float healthFractionPerHit; + + public static float healthCostFraction; + + public static string impactSoundString; + + public override void OnEnter() + { + base.OnEnter(); + if (NetworkServer.active && (bool)base.healthComponent && healthCostFraction >= Mathf.Epsilon) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + } + + protected override void AddDebuff(CharacterBody body) + { + body.healthComponent.GetComponent()?.SetStun(-1f); + if ((bool)hitEffectPrefab) + { + EffectManager.SpawnEffect(hitEffectPrefab, new EffectData + { + origin = body.corePosition + }, transmit: true); + } + if ((bool)base.healthComponent) + { + HealOrb healOrb = new HealOrb(); + healOrb.origin = body.corePosition; + healOrb.target = base.healthComponent.body.mainHurtBox; + healOrb.healValue = healthFractionPerHit * base.healthComponent.fullHealth; + healOrb.overrideDuration = Random.Range(0.3f, 0.6f); + OrbManager.instance.AddOrb(healOrb); + } + Util.PlaySound(impactSoundString, base.gameObject); + } + + protected override float CalculateDamage() + { + return damageCoefficient * damageStat; + } + + protected override float CalculateProcCoefficient() + { + return procCoefficient; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSonicBoom.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSonicBoom.cs new file mode 100644 index 0000000..4bbec85 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSonicBoom.cs @@ -0,0 +1,171 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Treebot.Weapon; + +public class FireSonicBoom : BaseState +{ + [SerializeField] + public string sound; + + [SerializeField] + public string muzzle; + + [SerializeField] + public GameObject fireEffectPrefab; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float fieldOfView; + + [SerializeField] + public float backupDistance; + + [SerializeField] + public float maxDistance; + + [SerializeField] + public float idealDistanceToPlaceTargets; + + [SerializeField] + public float liftVelocity; + + [SerializeField] + public float slowDuration; + + [SerializeField] + public float groundKnockbackDistance; + + [SerializeField] + public float airKnockbackDistance; + + public static AnimationCurve shoveSuitabilityCurve; + + private float duration; + + private static int FireSonicBoomStateHash = Animator.StringToHash("FireSonicBoom"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", FireSonicBoomStateHash); + Util.PlaySound(sound, base.gameObject); + Ray aimRay = GetAimRay(); + if (!string.IsNullOrEmpty(muzzle)) + { + EffectManager.SimpleMuzzleFlash(fireEffectPrefab, base.gameObject, muzzle, transmit: false); + } + else + { + EffectManager.SpawnEffect(fireEffectPrefab, new EffectData + { + origin = aimRay.origin, + rotation = Quaternion.LookRotation(aimRay.direction) + }, transmit: false); + } + aimRay.origin -= aimRay.direction * backupDistance; + if (NetworkServer.active) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.all; + bullseyeSearch.maxAngleFilter = fieldOfView * 0.5f; + bullseyeSearch.maxDistanceFilter = maxDistance; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + IEnumerable enumerable = bullseyeSearch.GetResults().Where(Util.IsValid).Distinct(default(HurtBox.EntityEqualityComparer)); + TeamIndex team = GetTeam(); + foreach (HurtBox item in enumerable) + { + if (FriendlyFireManager.ShouldSplashHitProceed(item.healthComponent, team)) + { + Vector3 vector = item.transform.position - aimRay.origin; + float magnitude = vector.magnitude; + _ = new Vector2(vector.x, vector.z).magnitude; + Vector3 vector2 = vector / magnitude; + float num = 1f; + CharacterBody body = item.healthComponent.body; + if ((bool)body.characterMotor) + { + num = body.characterMotor.mass; + } + else if ((bool)item.healthComponent.GetComponent()) + { + num = base.rigidbody.mass; + } + float num2 = shoveSuitabilityCurve.Evaluate(num); + AddDebuff(body); + body.RecalculateStats(); + float acceleration = body.acceleration; + Vector3 vector3 = vector2; + float num3 = Trajectory.CalculateInitialYSpeedForHeight(Mathf.Abs(idealDistanceToPlaceTargets - magnitude), 0f - acceleration) * Mathf.Sign(idealDistanceToPlaceTargets - magnitude); + vector3 *= num3; + vector3.y = liftVelocity; + DamageInfo damageInfo = new DamageInfo + { + attacker = base.gameObject, + damage = CalculateDamage(), + position = item.transform.position, + procCoefficient = CalculateProcCoefficient() + }; + item.healthComponent.TakeDamageForce(vector3 * (num * num2), alwaysApply: true, disableAirControlUntilCollision: true); + item.healthComponent.TakeDamage(new DamageInfo + { + attacker = base.gameObject, + damage = CalculateDamage(), + position = item.transform.position, + procCoefficient = CalculateProcCoefficient() + }); + GlobalEventManager.instance.OnHitEnemy(damageInfo, item.healthComponent.gameObject); + } + } + } + if (base.isAuthority && (bool)base.characterBody && (bool)base.characterBody.characterMotor) + { + float height = (base.characterBody.characterMotor.isGrounded ? groundKnockbackDistance : airKnockbackDistance); + float num4 = (base.characterBody.characterMotor ? base.characterBody.characterMotor.mass : 1f); + float acceleration2 = base.characterBody.acceleration; + float num5 = Trajectory.CalculateInitialYSpeedForHeight(height, 0f - acceleration2); + base.characterBody.characterMotor.ApplyForce((0f - num5) * num4 * aimRay.direction); + } + } + + protected virtual void AddDebuff(CharacterBody body) + { + body.AddTimedBuff(RoR2Content.Buffs.Weak, slowDuration); + body.healthComponent.GetComponent()?.SetStun(-1f); + } + + protected virtual float CalculateDamage() + { + return 0f; + } + + protected virtual float CalculateProcCoefficient() + { + return 0f; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSonicPull.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSonicPull.cs new file mode 100644 index 0000000..142f029 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSonicPull.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Treebot.Weapon; + +public class FireSonicPull : FireSonicBoom +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSyringe.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSyringe.cs new file mode 100644 index 0000000..d80a1e0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot.Weapon/FireSyringe.cs @@ -0,0 +1,93 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Treebot.Weapon; + +public class FireSyringe : BaseState +{ + public static GameObject projectilePrefab; + + public static GameObject finalProjectilePrefab; + + public static GameObject muzzleflashEffectPrefab; + + public static int projectileCount = 3; + + public static float totalYawSpread = 5f; + + public static float baseDuration = 2f; + + public static float baseFireDuration = 0.2f; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string attackSound; + + public static string finalAttackSound; + + public static string muzzleName; + + private float duration; + + private float fireDuration; + + private int projectilesFired; + + private static int FireSyringeStateHash = Animator.StringToHash("FireSyringe"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + fireDuration = baseFireDuration / attackSpeedStat; + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + int num = Mathf.FloorToInt(base.fixedAge / fireDuration * (float)projectileCount); + if (projectilesFired <= num && projectilesFired < projectileCount) + { + GameObject prefab = projectilePrefab; + string soundString = attackSound; + if (projectilesFired == projectileCount - 1) + { + prefab = finalProjectilePrefab; + soundString = finalAttackSound; + } + PlayAnimation("Gesture, Additive", FireSyringeStateHash); + Util.PlaySound(soundString, base.gameObject); + base.characterBody.SetAimTimer(3f); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + float bonusYaw = (float)Mathf.FloorToInt((float)projectilesFired - (float)(projectileCount - 1) / 2f) / (float)(projectileCount - 1) * totalYawSpread; + Vector3 forward = Util.ApplySpread(ray.direction, 0f, 0f, 1f, 1f, bonusYaw); + ProjectileManager.instance.FireProjectile(prefab, ray.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + projectilesFired++; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowDash.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowDash.cs new file mode 100644 index 0000000..d87d061 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowDash.cs @@ -0,0 +1,242 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class BurrowDash : BaseCharacterMain +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public static AnimationCurve speedMultiplier; + + public static float chargeDamageCoefficient; + + public static GameObject impactEffectPrefab; + + public static GameObject burrowLoopEffectPrefab; + + public static float hitPauseDuration; + + public static float timeBeforeExitToPlayExitAnimation; + + public static string impactSoundString; + + public static string startSoundString; + + public static string endSoundString; + + public static float healPercent; + + public static bool resetDurationOnImpact; + + [SerializeField] + public GameObject startEffectPrefab; + + [SerializeField] + public GameObject endEffectPrefab; + + private float duration; + + private float hitPauseTimer; + + private Vector3 idealDirection; + + private OverlapAttack attack; + + private ChildLocator childLocator; + + private bool inHitPause; + + private bool beginPlayingExitAnimation; + + private Transform modelTransform; + + private GameObject burrowLoopEffectInstance; + + private int originalLayer; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + if (base.isAuthority) + { + if ((bool)base.inputBank) + { + idealDirection = base.inputBank.aimDirection; + idealDirection.y = 0f; + } + UpdateDirection(); + } + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = true; + } + if ((bool)startEffectPrefab && (bool)base.characterBody) + { + EffectManager.SpawnEffect(startEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: false); + } + if ((bool)base.characterDirection) + { + base.characterDirection.forward = idealDirection; + } + Util.PlaySound(startSoundString, base.gameObject); + PlayCrossfade("Body", "BurrowEnter", 0.1f); + HitBoxGroup hitBoxGroup = null; + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "BurrowCharge"); + childLocator = modelTransform.GetComponent(); + } + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = TeamComponent.GetObjectTeam(attack.attacker); + attack.damage = chargeDamageCoefficient * damageStat; + attack.hitEffectPrefab = impactEffectPrefab; + attack.hitBoxGroup = hitBoxGroup; + attack.damage = damageStat * chargeDamageCoefficient; + attack.damageType = DamageType.Freeze2s; + attack.procCoefficient = 1f; + originalLayer = base.gameObject.layer; + base.gameObject.layer = LayerIndex.debris.intVal; + base.characterMotor.Motor.RebuildCollidableLayers(); + modelTransform.GetComponent().hurtBoxesDeactivatorCounter++; + base.characterBody.hideCrosshair = true; + base.characterBody.isSprinting = true; + if ((bool)childLocator) + { + Transform transform = childLocator.FindChild("BurrowCenter"); + if ((bool)transform && (bool)burrowLoopEffectPrefab) + { + burrowLoopEffectInstance = UnityEngine.Object.Instantiate(burrowLoopEffectPrefab, transform.position, transform.rotation); + burrowLoopEffectInstance.transform.parent = transform; + } + } + } + + public override void OnExit() + { + if ((bool)base.characterBody && !outer.destroying && (bool)endEffectPrefab) + { + EffectManager.SpawnEffect(endEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition + }, transmit: false); + } + Util.PlaySound(endSoundString, base.gameObject); + base.gameObject.layer = originalLayer; + base.characterMotor.Motor.RebuildCollidableLayers(); + modelTransform.GetComponent().hurtBoxesDeactivatorCounter--; + base.characterBody.hideCrosshair = false; + if ((bool)burrowLoopEffectInstance) + { + EntityState.Destroy(burrowLoopEffectInstance); + } + Animator animator = GetModelAnimator(); + int layerIndex = animator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, 2f); + animator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + base.OnExit(); + } + + private void UpdateDirection() + { + if ((bool)base.inputBank) + { + Vector2 vector = Util.Vector3XZToVector2XY(base.inputBank.moveVector); + if (vector != Vector2.zero) + { + vector.Normalize(); + idealDirection = new Vector3(vector.x, 0f, vector.y).normalized; + } + } + } + + protected override void UpdateAnimationParameters() + { + } + + private Vector3 GetIdealVelocity() + { + return base.characterDirection.forward * base.characterBody.moveSpeed * speedMultiplier.Evaluate(base.fixedAge / duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + return; + } + if (base.fixedAge >= duration - timeBeforeExitToPlayExitAnimation && !beginPlayingExitAnimation) + { + beginPlayingExitAnimation = true; + PlayCrossfade("Body", "BurrowExit", 0.1f); + } + if (!base.isAuthority) + { + return; + } + UpdateDirection(); + if (!inHitPause) + { + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = idealDirection; + if ((bool)base.characterMotor && !base.characterMotor.disableAirControlUntilCollision) + { + base.characterMotor.rootMotion += GetIdealVelocity() * GetDeltaTime(); + } + } + if (attack.Fire()) + { + Util.PlaySound(impactSoundString, base.gameObject); + inHitPause = true; + hitPauseTimer = hitPauseDuration; + if (healPercent > 0f) + { + base.healthComponent.HealFraction(healPercent, default(ProcChainMask)); + Util.PlaySound("Play_item_use_fruit", base.gameObject); + EffectData effectData = new EffectData(); + effectData.origin = base.transform.position; + effectData.SetNetworkedObjectReference(base.gameObject); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/FruitHealEffect"), effectData, transmit: true); + } + if (resetDurationOnImpact) + { + base.fixedAge = 0f; + } + else + { + base.fixedAge -= hitPauseDuration; + } + } + } + else + { + base.characterMotor.velocity = Vector3.zero; + hitPauseTimer -= GetDeltaTime(); + if (hitPauseTimer < 0f) + { + inHitPause = false; + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowIn.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowIn.cs new file mode 100644 index 0000000..406cdd4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowIn.cs @@ -0,0 +1,63 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class BurrowIn : BaseState +{ + public static GameObject burrowPrefab; + + public static float baseDuration; + + public static string burrowInSoundString; + + private float stopwatch; + + private float duration; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private CameraTargetParams.AimRequest aimRequest; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayCrossfade("Body", "BurrowIn", "BurrowIn.playbackRate", duration, 0.1f); + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + Util.PlaySound(burrowInSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + if ((bool)base.characterBody) + { + base.characterBody.hideCrosshair = true; + } + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + } + + public override void OnExit() + { + aimRequest?.Dispose(); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + Burrowed nextState = new Burrowed(); + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowOut.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowOut.cs new file mode 100644 index 0000000..c63233e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/BurrowOut.cs @@ -0,0 +1,54 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class BurrowOut : GenericCharacterMain +{ + public static GameObject burrowPrefab; + + public static float baseDuration; + + public static string burrowOutSoundString; + + public static float jumpVelocity; + + private float stopwatch; + + private Transform modelTransform; + + private ChildLocator childLocator; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + childLocator = modelTransform.GetComponent(); + Util.PlaySound(burrowOutSoundString, base.gameObject); + EffectManager.SimpleMuzzleFlash(burrowPrefab, base.gameObject, "BurrowCenter", transmit: false); + base.characterMotor.velocity = new Vector3(0f, jumpVelocity, 0f); + base.characterMotor.Motor.ForceUnground(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/Burrowed.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/Burrowed.cs new file mode 100644 index 0000000..5b45061 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/Burrowed.cs @@ -0,0 +1,66 @@ +using EntityStates.Treebot.Weapon; +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class Burrowed : GenericCharacterMain +{ + public static float mortarCooldown; + + public static string primarySkillName; + + public static string altPrimarySkillName; + + public static string utilitySkillName; + + public static string altUtilitySkillName; + + public float duration; + + private ChildLocator childLocator; + + private CameraTargetParams.AimRequest aimRequest; + + public override void OnEnter() + { + base.OnEnter(); + PlayCrossfade("Body", "Burrowed", 0.1f); + base.skillLocator.primary = base.skillLocator.FindSkill(altPrimarySkillName); + base.skillLocator.utility = base.skillLocator.FindSkill(altUtilitySkillName); + base.skillLocator.primary.stateMachine.mainStateType = new SerializableEntityStateType(typeof(AimMortar)); + base.skillLocator.primary.stateMachine.SetNextStateToMain(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + } + if ((bool)childLocator) + { + base.characterBody.aimOriginTransform = childLocator.FindChild("AimOriginMortar"); + } + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + } + + public override void OnExit() + { + aimRequest?.Dispose(); + base.skillLocator.primary = base.skillLocator.FindSkill(primarySkillName); + base.skillLocator.utility = base.skillLocator.FindSkill(utilitySkillName); + base.skillLocator.primary.stateMachine.mainStateType = new SerializableEntityStateType(typeof(Idle)); + base.skillLocator.primary.stateMachine.SetNextStateToMain(); + if ((bool)childLocator) + { + base.characterBody.aimOriginTransform = childLocator.FindChild("AimOriginSyringe"); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/FlowerProjectileHover.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/FlowerProjectileHover.cs new file mode 100644 index 0000000..2f39ece --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/FlowerProjectileHover.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using EntityStates.Toolbot; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class FlowerProjectileHover : DroneProjectileHover +{ + public static float yankSpeed; + + public static AnimationCurve yankSuitabilityCurve; + + public static float healthFractionYieldPerHit; + + private GameObject owner; + + private ProcChainMask procChainMask; + + private float procCoefficient; + + private float damage; + + private DamageTypeCombo damageType; + + private bool crit; + + private TeamIndex teamIndex = TeamIndex.None; + + private float healPulseHealthFractionValue; + + public override void OnEnter() + { + base.OnEnter(); + ProjectileController component = GetComponent(); + if ((bool)component) + { + owner = component.owner; + procChainMask = component.procChainMask; + procCoefficient = component.procCoefficient; + teamIndex = component.teamFilter.teamIndex; + } + ProjectileDamage component2 = GetComponent(); + if ((bool)component2) + { + damage = component2.damage; + damageType = component2.damageType; + crit = component2.crit; + } + } + + private void FirstPulse() + { + Vector3 position = base.transform.position; + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = position; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(teamIndex); + bullseyeSearch.maxDistanceFilter = pulseRadius; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.filterByLoS = true; + bullseyeSearch.filterByDistinctEntity = true; + bullseyeSearch.RefreshCandidates(); + IEnumerable results = bullseyeSearch.GetResults(); + int num = 0; + foreach (HurtBox item in results) + { + num++; + Vector3 vector = item.transform.position - position; + float magnitude = vector.magnitude; + Vector3 vector2 = vector / magnitude; + Rigidbody component = item.healthComponent.GetComponent(); + float num2 = (component ? component.mass : 1f); + float num3 = yankSuitabilityCurve.Evaluate(num2); + Vector3 force = vector2 * (num2 * num3 * (0f - yankSpeed)); + DamageInfo damageInfo = new DamageInfo + { + attacker = owner, + inflictor = base.gameObject, + crit = crit, + damage = damage, + damageColorIndex = DamageColorIndex.Default, + damageType = damageType, + force = force, + position = item.transform.position, + procChainMask = procChainMask, + procCoefficient = procCoefficient + }; + item.healthComponent.TakeDamage(damageInfo); + } + healPulseHealthFractionValue = (float)num * healthFractionYieldPerHit / (float)(pulseCount - 1); + } + + private void HealPulse() + { + if ((bool)owner) + { + HealthComponent component = owner.GetComponent(); + if ((bool)component) + { + component.HealFraction(healPulseHealthFractionValue, procChainMask); + } + } + } + + protected override void Pulse() + { + if (pulses == 1) + { + FirstPulse(); + } + else + { + HealPulse(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/TreebotFireFruitSeed.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/TreebotFireFruitSeed.cs new file mode 100644 index 0000000..027bef9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/TreebotFireFruitSeed.cs @@ -0,0 +1,78 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class TreebotFireFruitSeed : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public string animationLayerName = "Gesture, Additive"; + + [SerializeField] + public string animationStateName = "FireFlower"; + + [SerializeField] + public string playbackRateParam = "FireFlower.playbackRate"; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, duration); + if (base.isAuthority) + { + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.damage = damageCoefficient * damageStat; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.force = 0f; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.rotation = Quaternion.LookRotation(ray.direction); + fireProjectileInfo.useSpeedOverride = false; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Treebot/TreebotPrepFruitSeed.cs b/ilspy_dump/ror2_csproj/EntityStates.Treebot/TreebotPrepFruitSeed.cs new file mode 100644 index 0000000..ae344a5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Treebot/TreebotPrepFruitSeed.cs @@ -0,0 +1,46 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Treebot; + +public class TreebotPrepFruitSeed : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string animationLayerName = "Gesture, Additive"; + + [SerializeField] + public string animationStateName = "PrepFlower"; + + [SerializeField] + public string playbackRateParam = "PrepFlower.playbackRate"; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, playbackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new TreebotFireFruitSeed()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Turret1/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Turret1/DeathState.cs new file mode 100644 index 0000000..e7eb199 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Turret1/DeathState.cs @@ -0,0 +1,7 @@ +using EntityStates.EngiTurret; + +namespace EntityStates.Turret1; + +public class DeathState : EntityStates.EngiTurret.DeathState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Turret1/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Turret1/SpawnState.cs new file mode 100644 index 0000000..7b4da3e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Turret1/SpawnState.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace EntityStates.Turret1; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)GetModelAnimator()) + { + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, 1.5f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunFire.cs b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunFire.cs new file mode 100644 index 0000000..78bd297 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunFire.cs @@ -0,0 +1,112 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.UrchinTurret.Weapon; + +public class MinigunFire : MinigunState +{ + public static GameObject muzzleVfxPrefab; + + public static GameObject projectilePrefab; + + public static float baseFireInterval; + + public static float baseDamagePerSecondCoefficient; + + public static float bulletMinSpread; + + public static float bulletMaxSpread; + + public static string fireSound; + + public static string startSound; + + public static string endSound; + + private float fireTimer; + + private Transform muzzleVfxTransform; + + private float baseFireRate; + + private float baseBulletsPerSecond; + + private Run.FixedTimeStamp critEndTime; + + private Run.FixedTimeStamp lastCritCheck; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)muzzleTransform && (bool)muzzleVfxPrefab) + { + muzzleVfxTransform = Object.Instantiate(muzzleVfxPrefab, muzzleTransform).transform; + } + baseFireRate = 1f / baseFireInterval; + baseBulletsPerSecond = baseFireRate; + critEndTime = Run.FixedTimeStamp.negativeInfinity; + lastCritCheck = Run.FixedTimeStamp.negativeInfinity; + Util.PlaySound(startSound, base.gameObject); + PlayCrossfade("Gesture, Additive", "ShootLoop", 0.2f); + } + + private void UpdateCrits() + { + if (lastCritCheck.timeSince >= 1f) + { + lastCritCheck = Run.FixedTimeStamp.now; + if (RollCrit()) + { + critEndTime = Run.FixedTimeStamp.now + 2f; + } + } + } + + public override void OnExit() + { + Util.PlaySound(endSound, base.gameObject); + if ((bool)muzzleVfxTransform) + { + EntityState.Destroy(muzzleVfxTransform.gameObject); + muzzleVfxTransform = null; + } + PlayCrossfade("Gesture, Additive", "BufferEmpty", 0.2f); + base.OnExit(); + } + + private void OnFireShared() + { + Util.PlaySound(fireSound, base.gameObject); + if (base.isAuthority) + { + OnFireAuthority(); + } + } + + private void OnFireAuthority() + { + UpdateCrits(); + bool crit = !critEndTime.hasPassed; + float damage = baseDamagePerSecondCoefficient / baseBulletsPerSecond * damageStat; + Ray aimRay = GetAimRay(); + Vector3 forward = Util.ApplySpread(aimRay.direction, bulletMinSpread, bulletMaxSpread, 1f, 1f); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damage, 0f, crit); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + if (fireTimer <= 0f) + { + float num = baseFireInterval / attackSpeedStat; + fireTimer += num; + OnFireShared(); + } + if (base.isAuthority && !base.skillButtonState.down) + { + outer.SetNextState(new MinigunSpinDown()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunSpinDown.cs b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunSpinDown.cs new file mode 100644 index 0000000..4b1418b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunSpinDown.cs @@ -0,0 +1,28 @@ +using RoR2; + +namespace EntityStates.UrchinTurret.Weapon; + +public class MinigunSpinDown : MinigunState +{ + public static float baseDuration; + + public static string sound; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(sound, base.gameObject, attackSpeedStat); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunSpinUp.cs b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunSpinUp.cs new file mode 100644 index 0000000..b5a0254 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunSpinUp.cs @@ -0,0 +1,80 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.UrchinTurret.Weapon; + +public class MinigunSpinUp : MinigunState +{ + public static float baseDuration; + + public static string sound; + + public static GameObject chargeEffectPrefab; + + private GameObject chargeInstance; + + private float duration; + + private EffectManagerHelper _emh_chargeInstance; + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeInstance = null; + _emh_chargeInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(sound, base.gameObject); + PlayCrossfade("Gesture, Additive", "EnterShootLoop", 0.2f); + if ((bool)muzzleTransform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + } + else + { + _emh_chargeInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + chargeInstance = _emh_chargeInstance.gameObject; + } + chargeInstance.transform.parent = muzzleTransform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new MinigunFire()); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeInstance) + { + if (_emh_chargeInstance != null && _emh_chargeInstance.OwningPool != null) + { + _emh_chargeInstance.OwningPool.ReturnObject(_emh_chargeInstance); + } + else + { + EntityState.Destroy(chargeInstance); + } + _emh_chargeInstance = null; + chargeInstance = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunState.cs b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunState.cs new file mode 100644 index 0000000..40bcc40 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret.Weapon/MinigunState.cs @@ -0,0 +1,35 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.UrchinTurret.Weapon; + +public class MinigunState : BaseState +{ + public static string muzzleName; + + protected Transform muzzleTransform; + + protected ref InputBankTest.ButtonState skillButtonState => ref base.inputBank.skill1; + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + StartAimMode(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret/DeathState.cs new file mode 100644 index 0000000..984ee11 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret/DeathState.cs @@ -0,0 +1,37 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.UrchinTurret; + +public class DeathState : BaseState +{ + public static GameObject initialExplosion; + + public static float effectScale; + + public static string deathString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(deathString, base.gameObject); + Transform transform = FindModelChild("Muzzle"); + if (base.isAuthority) + { + if ((bool)initialExplosion) + { + EffectManager.SpawnEffect(initialExplosion, new EffectData + { + origin = transform.position, + scale = effectScale + }, transmit: true); + } + EntityState.Destroy(base.gameObject); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret/SpawnState.cs new file mode 100644 index 0000000..554e060 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.UrchinTurret/SpawnState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.UrchinTurret; + +public class SpawnState : GenericCharacterSpawnState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster.Weapon/JellyBarrage.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster.Weapon/JellyBarrage.cs new file mode 100644 index 0000000..a8d0c20 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster.Weapon/JellyBarrage.cs @@ -0,0 +1,84 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VagrantMonster.Weapon; + +public class JellyBarrage : BaseState +{ + private float stopwatch; + + private float missileStopwatch; + + public static float baseDuration; + + public static string muzzleString; + + public static float missileSpawnFrequency; + + public static float missileSpawnDelay; + + public static float damageCoefficient; + + public static float maxSpread; + + public static GameObject projectilePrefab; + + public static GameObject muzzleflashPrefab; + + private ChildLocator childLocator; + + public override void OnEnter() + { + base.OnEnter(); + missileStopwatch -= missileSpawnDelay; + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + if ((bool)childLocator) + { + _ = (bool)childLocator.FindChild(muzzleString); + } + } + } + + private void FireBlob(Ray projectileRay, float bonusPitch, float bonusYaw) + { + projectileRay.direction = Util.ApplySpread(projectileRay.direction, 0f, maxSpread, 1f, 1f, bonusYaw, bonusPitch); + ProjectileManager.instance.FireProjectile(projectilePrefab, projectileRay.origin, Util.QuaternionSafeLookRotation(projectileRay.direction), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + missileStopwatch += deltaTime; + if (missileStopwatch >= 1f / missileSpawnFrequency) + { + missileStopwatch -= 1f / missileSpawnFrequency; + Transform transform = childLocator.FindChild(muzzleString); + if ((bool)transform) + { + Ray projectileRay = default(Ray); + projectileRay.origin = transform.position; + projectileRay.direction = GetAimRay().direction; + float maxDistance = 1000f; + if (Physics.Raycast(GetAimRay(), out var hitInfo, maxDistance, LayerIndex.world.mask)) + { + projectileRay.direction = hitInfo.point - transform.position; + } + FireBlob(projectileRay, 0f, 0f); + } + } + if (stopwatch >= baseDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster.Weapon/JellyStorm.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster.Weapon/JellyStorm.cs new file mode 100644 index 0000000..34345d1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster.Weapon/JellyStorm.cs @@ -0,0 +1,105 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VagrantMonster.Weapon; + +public class JellyStorm : BaseState +{ + private float stopwatch; + + private float missileStopwatch; + + public static float stormDuration; + + public static float stormToIdleTransitionDuration; + + public static string stormPointChildString; + + public static float missileSpawnFrequency; + + public static float missileSpawnDelay; + + public static int missileTurretCount; + + public static float missileTurretYawFrequency; + + public static float missileTurretPitchFrequency; + + public static float missileTurretPitchMagnitude; + + public static float missileSpeed; + + public static float damageCoefficient; + + public static GameObject projectilePrefab; + + public static GameObject effectPrefab; + + private bool beginExitTransition; + + private ChildLocator childLocator; + + private static int StormEnterStateHash = Animator.StringToHash("StormEnter"); + + public override void OnEnter() + { + base.OnEnter(); + missileStopwatch -= missileSpawnDelay; + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + PlayAnimation("Gesture", StormEnterStateHash); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + childLocator = modelTransform.GetComponent(); + if ((bool)childLocator) + { + _ = (bool)childLocator.FindChild(stormPointChildString); + } + } + } + + private void FireBlob(Ray aimRay, float bonusPitch, float bonusYaw, float speed) + { + Vector3 forward = Util.ApplySpread(aimRay.direction, 0f, 0f, 1f, 1f, bonusYaw, bonusPitch); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, speed); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float deltaTime = GetDeltaTime(); + stopwatch += deltaTime; + missileStopwatch += deltaTime; + if (missileStopwatch >= 1f / missileSpawnFrequency && !beginExitTransition) + { + missileStopwatch -= 1f / missileSpawnFrequency; + Transform transform = childLocator.FindChild(stormPointChildString); + if ((bool)transform) + { + for (int i = 0; i < missileTurretCount; i++) + { + float bonusYaw = 360f / (float)missileTurretCount * (float)i + 360f * missileTurretYawFrequency * stopwatch; + float bonusPitch = Mathf.Sin(MathF.PI * 2f * missileTurretPitchFrequency * stopwatch) * missileTurretPitchMagnitude; + Ray aimRay = default(Ray); + aimRay.origin = transform.position; + aimRay.direction = transform.transform.forward; + FireBlob(aimRay, bonusPitch, bonusYaw, missileSpeed); + } + } + } + if (stopwatch >= stormDuration - stormToIdleTransitionDuration && !beginExitTransition) + { + beginExitTransition = true; + PlayCrossfade("Gesture", "StormExit", "StormExit.playbackRate", stormToIdleTransitionDuration, 0.5f); + } + if (stopwatch >= stormDuration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ChargeMegaNova.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ChargeMegaNova.cs new file mode 100644 index 0000000..45a45f7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ChargeMegaNova.cs @@ -0,0 +1,150 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VagrantMonster; + +public class ChargeMegaNova : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargingEffectPrefab; + + public static GameObject areaIndicatorPrefab; + + public static string chargingSoundString; + + public static float novaRadius; + + private float duration; + + private float stopwatch; + + private GameObject chargeEffectInstance; + + private GameObject areaIndicatorInstance; + + private uint soundID; + + private EffectManagerHelper _emh_chargeEffectInstance; + + private EffectManagerHelper _emh_areaIndicatorInstance; + + private Vector3 _cachedScaleVector = Vector3.one; + + public override void Reset() + { + base.Reset(); + duration = 0f; + stopwatch = 0f; + chargeEffectInstance = null; + areaIndicatorInstance = null; + soundID = 0u; + _emh_chargeEffectInstance = null; + _emh_areaIndicatorInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayCrossfade("Gesture, Override", "ChargeMegaNova", "ChargeMegaNova.playbackRate", duration, 0.3f); + soundID = Util.PlayAttackSpeedSound(chargingSoundString, base.gameObject, attackSpeedStat); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("HullCenter"); + Transform transform2 = component.FindChild("NovaCenter"); + if ((bool)transform && (bool)chargingEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargingEffectPrefab)) + { + chargeEffectInstance = Object.Instantiate(chargingEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectInstance = EffectManager.GetAndActivatePooledEffect(chargingEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance = _emh_chargeEffectInstance.gameObject; + } + _cachedScaleVector.x = novaRadius; + _cachedScaleVector.y = novaRadius; + _cachedScaleVector.z = novaRadius; + chargeEffectInstance.transform.localScale = _cachedScaleVector; + chargeEffectInstance.transform.parent = transform; + chargeEffectInstance.GetComponent().newDuration = duration; + } + if ((bool)transform2 && (bool)areaIndicatorPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(areaIndicatorPrefab)) + { + areaIndicatorInstance = Object.Instantiate(areaIndicatorPrefab, transform2.position, transform2.rotation); + } + else + { + _emh_areaIndicatorInstance = EffectManager.GetAndActivatePooledEffect(areaIndicatorPrefab, transform2.position, transform2.rotation); + areaIndicatorInstance = _emh_areaIndicatorInstance.gameObject; + } + _cachedScaleVector.x = novaRadius * 2f; + _cachedScaleVector.y = novaRadius * 2f; + _cachedScaleVector.z = novaRadius * 2f; + areaIndicatorInstance.transform.localScale = _cachedScaleVector; + areaIndicatorInstance.transform.parent = transform2; + } + } + + public override void OnExit() + { + base.OnExit(); + AkSoundEngine.StopPlayingID(soundID); + if ((bool)chargeEffectInstance) + { + if (_emh_chargeEffectInstance != null && _emh_chargeEffectInstance.OwningPool != null) + { + _emh_chargeEffectInstance.OwningPool.ReturnObject(_emh_chargeEffectInstance); + } + else + { + EntityState.Destroy(chargeEffectInstance); + } + _emh_chargeEffectInstance = null; + chargeEffectInstance = null; + } + if ((bool)areaIndicatorInstance) + { + if (_emh_areaIndicatorInstance != null && _emh_areaIndicatorInstance.OwningPool != null) + { + _emh_areaIndicatorInstance.OwningPool.ReturnObject(_emh_areaIndicatorInstance); + } + else + { + EntityState.Destroy(areaIndicatorInstance); + } + _emh_areaIndicatorInstance = null; + areaIndicatorInstance = null; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + FireMegaNova fireMegaNova = new FireMegaNova(); + fireMegaNova.novaRadius = novaRadius; + outer.SetNextState(fireMegaNova); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ChargeTrackingBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ChargeTrackingBomb.cs new file mode 100644 index 0000000..ed568ea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ChargeTrackingBomb.cs @@ -0,0 +1,99 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VagrantMonster; + +public class ChargeTrackingBomb : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargingEffectPrefab; + + public static string chargingSoundString; + + private float duration; + + private float stopwatch; + + private GameObject chargeEffectInstance; + + private uint soundID; + + private EffectManagerHelper _emh_chargeEffectInstance; + + public override void Reset() + { + base.Reset(); + duration = 0f; + stopwatch = 0f; + chargeEffectInstance = null; + soundID = 0u; + _emh_chargeEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayCrossfade("Gesture, Override", "ChargeTrackingBomb", "ChargeTrackingBomb.playbackRate", duration, 0.3f); + soundID = Util.PlayAttackSpeedSound(chargingSoundString, base.gameObject, attackSpeedStat); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild("TrackingBombMuzzle"); + if ((bool)transform && (bool)chargingEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargingEffectPrefab)) + { + chargeEffectInstance = Object.Instantiate(chargingEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectInstance = EffectManager.GetAndActivatePooledEffect(chargingEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance = _emh_chargeEffectInstance.gameObject; + } + chargeEffectInstance.transform.parent = transform; + chargeEffectInstance.GetComponent().newDuration = duration; + } + } + + public override void OnExit() + { + base.OnExit(); + AkSoundEngine.StopPlayingID(soundID); + if ((bool)chargeEffectInstance) + { + if (_emh_chargeEffectInstance != null && _emh_chargeEffectInstance.OwningPool != null) + { + _emh_chargeEffectInstance.OwningPool.ReturnObject(_emh_chargeEffectInstance); + } + else + { + EntityState.Destroy(chargeEffectInstance); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextState(new FireTrackingBomb()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/DeathState.cs new file mode 100644 index 0000000..c7c2d63 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/DeathState.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VagrantMonster; + +public class DeathState : BaseState +{ + public static GameObject initialExplosion; + + public static string deathString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(deathString, base.gameObject); + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if (base.isAuthority && (bool)initialExplosion) + { + EffectManager.SimpleImpactEffect(initialExplosion, base.transform.position, Vector3.up, transmit: true); + } + EntityState.Destroy(base.gameObject); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ExplosionAttack.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ExplosionAttack.cs new file mode 100644 index 0000000..2173e80 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/ExplosionAttack.cs @@ -0,0 +1,90 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VagrantMonster; + +public class ExplosionAttack : BaseState +{ + public static float minRadius; + + public static float maxRadius; + + public static int explosionCount; + + public static float baseDuration; + + public static float damageCoefficient; + + public static float force; + + public static float damageScaling; + + public static GameObject novaEffectPrefab; + + private float explosionTimer; + + private float explosionInterval; + + private int explosionIndex; + + public override void OnEnter() + { + base.OnEnter(); + explosionInterval = baseDuration / (float)explosionCount; + explosionIndex = 0; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + explosionTimer -= GetDeltaTime(); + if (!(explosionTimer <= 0f)) + { + return; + } + if (explosionIndex >= explosionCount) + { + if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + else + { + explosionTimer += explosionInterval; + Explode(); + explosionIndex++; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + private void Explode() + { + float t = (float)explosionIndex / (float)(explosionCount - 1); + float num = Mathf.Lerp(minRadius, maxRadius, t); + EffectManager.SpawnEffect(novaEffectPrefab, new EffectData + { + origin = base.transform.position, + scale = num + }, transmit: false); + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * damageCoefficient * Mathf.Pow(damageScaling, explosionIndex); + blastAttack.baseForce = force; + blastAttack.position = base.transform.position; + blastAttack.radius = num; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.Fire(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/FireMegaNova.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/FireMegaNova.cs new file mode 100644 index 0000000..294e537 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/FireMegaNova.cs @@ -0,0 +1,102 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VagrantMonster; + +public class FireMegaNova : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject novaEffectPrefab; + + public static GameObject novaImpactEffectPrefab; + + public static string novaSoundString; + + public static float novaDamageCoefficient; + + public static float novaForce; + + public float novaRadius; + + private float duration; + + private float stopwatch; + + private static int FireMegaNovaStateHash = Animator.StringToHash("FireMegaNova"); + + private static int FireMegaNovaParamHash = Animator.StringToHash("FireMegaNova.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Override", FireMegaNovaStateHash, FireMegaNovaParamHash, duration); + Detonate(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void Detonate() + { + Vector3 position = base.transform.position; + Util.PlaySound(novaSoundString, base.gameObject); + if ((bool)novaEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(novaEffectPrefab, base.gameObject, "NovaCenter", transmit: false); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = 3f; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matVagrantEnergized"); + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + } + if (NetworkServer.active) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.baseDamage = damageStat * novaDamageCoefficient; + blastAttack.baseForce = novaForce; + blastAttack.bonusForce = Vector3.zero; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.crit = base.characterBody.RollCrit(); + blastAttack.damageColorIndex = DamageColorIndex.Default; + blastAttack.damageType = DamageType.Generic; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.inflictor = base.gameObject; + blastAttack.position = position; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = 3f; + blastAttack.radius = novaRadius; + blastAttack.losType = BlastAttack.LoSType.NearestHit; + blastAttack.teamIndex = base.teamComponent.teamIndex; + blastAttack.impactEffect = EffectCatalog.FindEffectIndexFromPrefab(novaImpactEffectPrefab); + blastAttack.Fire(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/FireTrackingBomb.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/FireTrackingBomb.cs new file mode 100644 index 0000000..596c659 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/FireTrackingBomb.cs @@ -0,0 +1,73 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VagrantMonster; + +public class FireTrackingBomb : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject projectilePrefab; + + public static GameObject muzzleEffectPrefab; + + public static string fireBombSoundString; + + public static float bombDamageCoefficient; + + public static float bombForce; + + public float novaRadius; + + private float duration; + + private float stopwatch; + + private static int FireTrackingBombStateHash = Animator.StringToHash("FireTrackingBomb"); + + private static int FireTrackingBombParamHash = Animator.StringToHash("FireTrackingBomb.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Override", FireTrackingBombStateHash, FireTrackingBombParamHash, duration); + FireBomb(); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireBomb() + { + Ray aimRay = GetAimRay(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + aimRay.origin = component.FindChild("TrackingBombMuzzle").transform.position; + } + } + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, "TrackingBombMuzzle", transmit: false); + if (base.isAuthority) + { + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * bombDamageCoefficient, bombForce, Util.CheckRoll(critStat, base.characterBody.master)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/SpawnState.cs new file mode 100644 index 0000000..7f99f10 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantMonster/SpawnState.cs @@ -0,0 +1,50 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VagrantMonster; + +public class SpawnState : BaseState +{ + private float stopwatch; + + public static float duration = 4f; + + public static string spawnSoundString; + + public static GameObject spawnEffectPrefab; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, "SpawnOrigin", transmit: false); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + modelTransform.GetComponent().enabled = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/BaseVagrantNovaItemState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/BaseVagrantNovaItemState.cs new file mode 100644 index 0000000..ec615e5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/BaseVagrantNovaItemState.cs @@ -0,0 +1,71 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VagrantNovaItem; + +public class BaseVagrantNovaItemState : BaseBodyAttachmentState +{ + protected ParticleSystem chargeSparks; + + protected int GetItemStack() + { + if (!base.attachedBody || !base.attachedBody.inventory) + { + return 1; + } + return base.attachedBody.inventory.GetItemCount(RoR2Content.Items.NovaOnLowHealth); + } + + public override void OnEnter() + { + base.OnEnter(); + ChildLocator component = GetComponent(); + if (!component) + { + return; + } + chargeSparks = component.FindChild("ChargeSparks")?.GetComponent(); + if ((bool)chargeSparks) + { + ParticleSystem.ShapeModule shape = chargeSparks.shape; + SkinnedMeshRenderer skinnedMeshRenderer = FindAttachedBodyMainRenderer(); + if ((bool)skinnedMeshRenderer) + { + shape.skinnedMeshRenderer = FindAttachedBodyMainRenderer(); + ParticleSystem.MainModule main = chargeSparks.main; + float x = skinnedMeshRenderer.transform.lossyScale.x; + main.startSize = 0.5f / x; + } + } + } + + protected void SetChargeSparkEmissionRateMultiplier(float multiplier) + { + if ((bool)chargeSparks) + { + ParticleSystem.EmissionModule emission = chargeSparks.emission; + emission.rateOverTimeMultiplier = multiplier * 20f; + } + } + + private SkinnedMeshRenderer FindAttachedBodyMainRenderer() + { + if (!base.attachedBody) + { + return null; + } + CharacterModel.RendererInfo[] array = base.attachedBody.modelLocator?.modelTransform.GetComponent()?.baseRendererInfos; + if (array == null) + { + return null; + } + for (int i = 0; i < array.Length; i++) + { + if (array[i].renderer is SkinnedMeshRenderer result) + { + return result; + } + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/ChargeState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/ChargeState.cs new file mode 100644 index 0000000..1dfc59d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/ChargeState.cs @@ -0,0 +1,76 @@ +using EntityStates.VagrantMonster; +using RoR2; +using UnityEngine; + +namespace EntityStates.VagrantNovaItem; + +public class ChargeState : BaseVagrantNovaItemState +{ + public static float baseDuration = 3f; + + public static string chargeSound; + + private float duration; + + private GameObject chargeVfxInstance; + + private GameObject areaIndicatorVfxInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / (base.attachedBody ? base.attachedBody.attackSpeed : 1f); + SetChargeSparkEmissionRateMultiplier(1f); + if ((bool)base.attachedBody) + { + Vector3 position = base.transform.position; + Quaternion rotation = base.transform.rotation; + chargeVfxInstance = Object.Instantiate(ChargeMegaNova.chargingEffectPrefab, position, rotation); + chargeVfxInstance.transform.localScale = Vector3.one * 0.25f; + Util.PlaySound(chargeSound, base.gameObject); + areaIndicatorVfxInstance = Object.Instantiate(ChargeMegaNova.areaIndicatorPrefab, position, rotation); + ObjectScaleCurve component = areaIndicatorVfxInstance.GetComponent(); + component.timeMax = duration; + component.baseScale = Vector3.one * DetonateState.blastRadius * 2f; + areaIndicatorVfxInstance.GetComponent().timeMax = duration; + } + RoR2Application.onLateUpdate += OnLateUpdate; + } + + public override void OnExit() + { + RoR2Application.onLateUpdate -= OnLateUpdate; + if ((object)chargeVfxInstance != null) + { + EntityState.Destroy(chargeVfxInstance); + chargeVfxInstance = null; + } + if ((object)areaIndicatorVfxInstance != null) + { + EntityState.Destroy(areaIndicatorVfxInstance); + areaIndicatorVfxInstance = null; + } + base.OnExit(); + } + + private void OnLateUpdate() + { + if ((bool)chargeVfxInstance) + { + chargeVfxInstance.transform.position = base.transform.position; + } + if ((bool)areaIndicatorVfxInstance) + { + areaIndicatorVfxInstance.transform.position = base.transform.position; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new DetonateState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/DetonateState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/DetonateState.cs new file mode 100644 index 0000000..396f1ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/DetonateState.cs @@ -0,0 +1,65 @@ +using EntityStates.VagrantMonster; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VagrantNovaItem; + +public class DetonateState : BaseVagrantNovaItemState +{ + public static float blastRadius; + + public static float blastDamageCoefficient; + + public static float blastProcCoefficient; + + public static float blastForce; + + public static float baseDuration; + + public static string explosionSound; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + if (NetworkServer.active && (bool)base.attachedBody) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.attachedBody.gameObject; + blastAttack.baseDamage = base.attachedBody.damage * blastDamageCoefficient; + blastAttack.baseForce = blastForce; + blastAttack.bonusForce = Vector3.zero; + blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; + blastAttack.crit = base.attachedBody.RollCrit(); + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.damageType = DamageType.Generic; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.inflictor = base.gameObject; + blastAttack.position = base.attachedBody.corePosition; + blastAttack.procChainMask = default(ProcChainMask); + blastAttack.procCoefficient = blastProcCoefficient; + blastAttack.radius = blastRadius; + blastAttack.losType = BlastAttack.LoSType.NearestHit; + blastAttack.teamIndex = base.attachedBody.teamComponent.teamIndex; + blastAttack.Fire(); + EffectData effectData = new EffectData(); + effectData.origin = base.attachedBody.corePosition; + effectData.SetHurtBoxReference(base.attachedBody.mainHurtBox); + EffectManager.SpawnEffect(FireMegaNova.novaEffectPrefab, effectData, transmit: true); + } + SetChargeSparkEmissionRateMultiplier(0f); + Util.PlaySound(explosionSound, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new RechargeState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/ReadyState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/ReadyState.cs new file mode 100644 index 0000000..b3413f9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/ReadyState.cs @@ -0,0 +1,39 @@ +using RoR2; + +namespace EntityStates.VagrantNovaItem; + +public class ReadyState : BaseVagrantNovaItemState +{ + private HealthComponent attachedHealthComponent; + + public override void OnEnter() + { + base.OnEnter(); + attachedHealthComponent = base.attachedBody?.healthComponent; + SetChargeSparkEmissionRateMultiplier(1f); + GlobalEventManager.onServerDamageDealt += OnDamaged; + } + + public override void OnExit() + { + base.OnExit(); + GlobalEventManager.onServerDamageDealt -= OnDamaged; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && attachedHealthComponent.isHealthLow) + { + outer.SetNextState(new ChargeState()); + } + } + + private void OnDamaged(DamageReport report) + { + if (report.hitLowHealth && (object)report?.victim?.body == base.attachedBody) + { + outer.SetNextState(new ChargeState()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/RechargeState.cs b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/RechargeState.cs new file mode 100644 index 0000000..eb7a956 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VagrantNovaItem/RechargeState.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +namespace EntityStates.VagrantNovaItem; + +public class RechargeState : BaseVagrantNovaItemState +{ + public static float baseDuration = 30f; + + public static AnimationCurve particleEmissionCurve; + + private float rechargeDuration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + int itemStack = GetItemStack(); + float num = baseDuration / (float)(itemStack + 1); + float num2 = base.fixedAge / num; + if (num2 >= 1f) + { + num2 = 1f; + outer.SetNextState(new ReadyState()); + } + SetChargeSparkEmissionRateMultiplier(particleEmissionCurve.Evaluate(num2)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vermin.Weapon/TongueLash.cs b/ilspy_dump/ror2_csproj/EntityStates.Vermin.Weapon/TongueLash.cs new file mode 100644 index 0000000..8e8fea2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vermin.Weapon/TongueLash.cs @@ -0,0 +1,21 @@ +using RoR2; + +namespace EntityStates.Vermin.Weapon; + +public class TongueLash : BasicMeleeAttack +{ + protected override void PlayAnimation() + { + PlayCrossfade("Gesture, Additive", "TongueLash", "TongueLash.playbackRate", duration, 0.1f); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vermin/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Vermin/SpawnState.cs new file mode 100644 index 0000000..5de448c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vermin/SpawnState.cs @@ -0,0 +1,5 @@ +namespace EntityStates.Vermin; + +public class SpawnState : GenericCharacterSpawnState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle.Weapon/ChargeFire.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle.Weapon/ChargeFire.cs new file mode 100644 index 0000000..7c444d8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle.Weapon/ChargeFire.cs @@ -0,0 +1,95 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidBarnacle.Weapon; + +public class ChargeFire : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject chargeVfxPrefab; + + [SerializeField] + public string attackSoundEffect; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateName; + + private float _chargingDuration; + + private float _totalDuration; + + private float _crossFadeDuration; + + private GameObject _chargeVfxInstance; + + public override void OnEnter() + { + base.OnEnter(); + _totalDuration = baseDuration / attackSpeedStat; + _crossFadeDuration = _totalDuration * 0.25f; + _chargingDuration = _totalDuration - _crossFadeDuration; + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackSoundEffect, base.gameObject, attackSpeedStat); + if (modelTransform != null) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("MuzzleMouth"); + if ((bool)transform && (bool)chargeVfxPrefab) + { + _chargeVfxInstance = Object.Instantiate(chargeVfxPrefab, transform.position, transform.rotation, transform); + ScaleParticleSystemDuration component2 = _chargeVfxInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = _totalDuration; + } + } + } + } + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateName, _chargingDuration, _crossFadeDuration); + } + + public override void Update() + { + base.Update(); + if ((bool)_chargeVfxInstance) + { + Ray aimRay = GetAimRay(); + _chargeVfxInstance.transform.forward = aimRay.direction; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= _totalDuration && base.isAuthority) + { + Fire nextState = new Fire(); + outer.SetNextState(nextState); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)_chargeVfxInstance) + { + EntityState.Destroy(_chargeVfxInstance); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle.Weapon/Fire.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle.Weapon/Fire.cs new file mode 100644 index 0000000..bac41fe --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle.Weapon/Fire.cs @@ -0,0 +1,64 @@ +using UnityEngine; + +namespace EntityStates.VoidBarnacle.Weapon; + +public class Fire : GenericProjectileBaseState +{ + [SerializeField] + public int numberOfFireballs; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateName; + + private float _interFireballDuration; + + private float _animationDuration; + + private Transform muzzleTransform; + + public override void OnEnter() + { + duration = baseDuration / attackSpeedStat; + _interFireballDuration = duration / (float)numberOfFireballs; + _animationDuration = _interFireballDuration; + muzzleTransform = FindModelChild(targetMuzzle); + base.OnEnter(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (stopwatch >= _animationDuration && numberOfFireballs > 0) + { + _animationDuration += _animationDuration; + PlayAnimation(_animationDuration); + } + } + + protected override void PlayAnimation(float duration) + { + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, _interFireballDuration); + } + + protected override void FireProjectile() + { + base.FireProjectile(); + if (numberOfFireballs > 1) + { + firedProjectile = false; + delayBeforeFiringProjectile += _interFireballDuration; + } + numberOfFireballs--; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/DeathState.cs new file mode 100644 index 0000000..29a92d2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/DeathState.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidBarnacle; + +public class DeathState : GenericCharacterDeath +{ + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static float duration; + + public static GameObject deathFXPrefab; + + public override void OnEnter() + { + base.OnEnter(); + if (deathFXPrefab != null) + { + EffectManager.SimpleEffect(deathFXPrefab, base.transform.position, base.transform.rotation, transmit: true); + } + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/FindSurface.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/FindSurface.cs new file mode 100644 index 0000000..91f5cf4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/FindSurface.cs @@ -0,0 +1,52 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidBarnacle; + +public class FindSurface : NoCastSpawn +{ + public static int raycastCount; + + public static float maxRaycastLength; + + public static float raycastSphereYOffset; + + public static float raycastMinimumAngle; + + public static float raycastMaximumAngle; + + private const float _cRadianConversionCoeficcient = MathF.PI / 180f; + + public override void OnEnter() + { + base.OnEnter(); + RaycastHit hitInfo = default(RaycastHit); + Vector3 origin = new Vector3(base.characterBody.corePosition.x, base.characterBody.corePosition.y + raycastSphereYOffset, base.characterBody.corePosition.z); + if (!base.isAuthority) + { + return; + } + raycastMinimumAngle = Mathf.Clamp(raycastMinimumAngle, 0f, raycastMaximumAngle); + raycastMaximumAngle = Mathf.Clamp(raycastMaximumAngle, raycastMinimumAngle, 90f); + raycastCount = Mathf.Abs(raycastCount); + float num = 360f / (float)raycastCount; + for (int i = 0; i < raycastCount; i++) + { + float minInclusive = num * (float)i; + float maxInclusive = num * (float)(i + 1) - 1f; + float f = UnityEngine.Random.Range(minInclusive, maxInclusive) * (MathF.PI / 180f); + float f2 = UnityEngine.Random.Range(raycastMinimumAngle, raycastMaximumAngle) * (MathF.PI / 180f); + float x = Mathf.Cos(f); + float y = Mathf.Sin(f2); + float z = Mathf.Sin(f); + Vector3 direction = new Vector3(x, y, z); + if (Physics.Raycast(origin, direction, out hitInfo, maxRaycastLength, LayerIndex.world.mask)) + { + base.transform.position = hitInfo.point; + base.transform.up = hitInfo.normal; + break; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/NoCastSpawn.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/NoCastSpawn.cs new file mode 100644 index 0000000..c36d980 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidBarnacle/NoCastSpawn.cs @@ -0,0 +1,48 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidBarnacle; + +public class NoCastSpawn : BaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateName; + + [SerializeField] + public float duration; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public GameObject spawnFXPrefab; + + [SerializeField] + public string spawnFXTransformName; + + public override void OnEnter() + { + base.OnEnter(); + if (spawnFXPrefab != null) + { + EffectManager.SimpleMuzzleFlash(spawnFXPrefab, base.gameObject, spawnFXTransformName, transmit: false); + } + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidCamp/Deactivate.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidCamp/Deactivate.cs new file mode 100644 index 0000000..8366223 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidCamp/Deactivate.cs @@ -0,0 +1,111 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidCamp; + +public class Deactivate : EntityState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string onEnterSoundString; + + [SerializeField] + public string baseAnimationLayerName; + + [SerializeField] + public string baseAnimationStateName; + + [SerializeField] + public string deactivateChildName; + + [SerializeField] + public string additiveAnimationLayerName; + + [SerializeField] + public string additiveAnimationStateName; + + [SerializeField] + public string completeObjectiveChatMessageToken; + + [SerializeField] + public PickupDropTable rewardDropTable; + + [SerializeField] + public GameObject rewardPickupPrefab; + + [SerializeField] + public bool dropItem; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(additiveAnimationLayerName, additiveAnimationStateName); + FogDamageController componentInChildren = outer.GetComponentInChildren(); + if ((bool)componentInChildren) + { + componentInChildren.enabled = false; + } + Util.PlaySound(onEnterSoundString, base.gameObject); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + modelChildLocator.FindChild("ActiveFX").gameObject.SetActive(value: false); + modelChildLocator.FindChild("RangeFX").GetComponent().enabled = true; + } + Chat.SendBroadcastChat(new Chat.SimpleChatMessage + { + baseToken = completeObjectiveChatMessageToken + }); + if (!NetworkServer.active || !dropItem) + { + return; + } + Transform transform = modelChildLocator.FindChild("RewardSpawnTarget"); + int participatingPlayerCount = Run.instance.participatingPlayerCount; + if (participatingPlayerCount > 0 && (bool)transform && (bool)rewardDropTable) + { + int num = participatingPlayerCount; + float angle = 360f / (float)num; + Vector3 vector = Quaternion.AngleAxis(Random.Range(0, 360), Vector3.up) * (Vector3.up * 40f + Vector3.forward * 5f); + Quaternion quaternion = Quaternion.AngleAxis(angle, Vector3.up); + Vector3 position = transform.transform.position; + PickupPickerController.Option[] pickerOptions = PickupPickerController.GenerateOptionsFromDropTable(3, rewardDropTable, Run.instance.treasureRng); + int num2 = 0; + while (num2 < num) + { + GenericPickupController.CreatePickupInfo pickupInfo = default(GenericPickupController.CreatePickupInfo); + pickupInfo.pickupIndex = PickupCatalog.FindPickupIndex(ItemTier.VoidTier2); + pickupInfo.pickerOptions = pickerOptions; + pickupInfo.rotation = Quaternion.identity; + pickupInfo.prefabOverride = rewardPickupPrefab; + pickupInfo.position = position; + PickupDropletController.CreatePickupDroplet(pickupInfo, position, vector); + num2++; + vector = quaternion * vector; + } + } + } + + public override void OnExit() + { + PlayAnimation(baseAnimationLayerName, baseAnimationStateName); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + modelChildLocator.FindChildGameObject(deactivateChildName).gameObject.SetActive(value: false); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(new EntityStates.Idle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidCamp/Idle.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidCamp/Idle.cs new file mode 100644 index 0000000..7557bcf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidCamp/Idle.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RoR2; +using RoR2.Audio; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidCamp; + +public class Idle : EntityState +{ + private class VoidCampObjectiveTracker : ObjectivePanelController.ObjectiveTracker + { + protected override string GenerateString() + { + int count = TeamComponent.GetTeamMembers(TeamIndex.Void).Count; + return string.Format(Language.GetString("OBJECTIVE_VOIDCAMP"), count); + } + + protected override bool IsDirty() + { + return true; + } + } + + [SerializeField] + public string baseAnimationLayerName; + + [SerializeField] + public string baseAnimationStateName; + + [SerializeField] + public string additiveAnimationLayerName; + + [SerializeField] + public string additiveAnimationStateName; + + [SerializeField] + public float clearCheckRate; + + [SerializeField] + public float initialClearCheckDelay; + + [SerializeField] + public LoopSoundDef loopSoundDef; + + [SerializeField] + public int indicatorMaxTeamCountThreshold; + + [SerializeField] + public GameObject indicatorPrefab; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + private bool hasEnabledIndicators; + + private HashSet indicatedNetIds; + + private float countdown; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(baseAnimationLayerName, baseAnimationStateName); + PlayAnimation(additiveAnimationLayerName, additiveAnimationStateName); + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSoundDef); + countdown = initialClearCheckDelay; + indicatedNetIds = new HashSet(); + GetComponent().enabled = true; + ObjectivePanelController.collectObjectiveSources += OnCollectObjectiveSources; + } + + private void OnCollectObjectiveSources(CharacterMaster master, List objectiveSourcesList) + { + objectiveSourcesList.Add(new ObjectivePanelController.ObjectiveSourceDescriptor + { + master = master, + objectiveType = typeof(VoidCampObjectiveTracker), + source = base.gameObject + }); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + countdown -= GetDeltaTime(); + if (!(countdown < 0f)) + { + return; + } + countdown = clearCheckRate; + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(TeamIndex.Void); + int count = teamMembers.Count; + if (count <= 0) + { + outer.SetNextState(new Deactivate()); + } + else + { + if (!hasEnabledIndicators && count > indicatorMaxTeamCountThreshold) + { + return; + } + hasEnabledIndicators = true; + foreach (TeamComponent item in teamMembers) + { + if ((bool)item && (bool)item.body && (bool)item.body.master) + { + RequestIndicatorForMaster(item.body.master); + } + } + } + } + + public override void OnExit() + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + GetComponent().enabled = false; + ObjectivePanelController.collectObjectiveSources -= OnCollectObjectiveSources; + base.OnExit(); + } + + protected void RequestIndicatorForMaster(CharacterMaster master) + { + if (indicatedNetIds.Contains(master.netId)) + { + return; + } + GameObject bodyObject = master.GetBodyObject(); + if ((bool)bodyObject) + { + TeamComponent component = bodyObject.GetComponent(); + if ((bool)component) + { + indicatedNetIds.Add(master.netId); + component.RequestDefaultIndicator(indicatorPrefab); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Death.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Death.cs new file mode 100644 index 0000000..c69bd26 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Death.cs @@ -0,0 +1,32 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidInfestor; + +public class Death : GenericCharacterDeath +{ + public static float deathDelay; + + public static GameObject deathEffectPrefab; + + private bool hasDied; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > deathDelay && NetworkServer.active && !hasDied) + { + hasDied = true; + EffectManager.SimpleImpactEffect(deathEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: true); + DestroyBodyAsapServer(); + EntityState.Destroy(base.gameObject); + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Infest.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Infest.cs new file mode 100644 index 0000000..11f6c2f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Infest.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.CharacterAI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidInfestor; + +public class Infest : BaseState +{ + public static GameObject enterEffectPrefab; + + public static GameObject successfulInfestEffectPrefab; + + public static GameObject infestVfxPrefab; + + public static string enterSoundString; + + public static float searchMaxDistance; + + public static float searchMaxAngle; + + public static float velocityInitialSpeed; + + public static float velocityTurnRate; + + public static float infestDamageCoefficient; + + private Transform targetTransform; + + private GameObject infestVfxInstance; + + private OverlapAttack attack; + + private List victimsStruck = new List(); + + private static int InfestStateHash = Animator.StringToHash("Infest"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Base", InfestStateHash); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)enterEffectPrefab) + { + EffectManager.SimpleImpactEffect(enterEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: false); + } + if ((bool)infestVfxPrefab) + { + infestVfxInstance = UnityEngine.Object.Instantiate(infestVfxPrefab, base.transform.position, Quaternion.identity); + infestVfxInstance.transform.parent = base.transform; + } + HitBoxGroup hitBoxGroup = null; + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == "Infest"); + } + attack = new OverlapAttack(); + attack.attacker = base.gameObject; + attack.inflictor = base.gameObject; + attack.teamIndex = GetTeam(); + attack.damage = infestDamageCoefficient * damageStat; + attack.hitEffectPrefab = null; + attack.hitBoxGroup = hitBoxGroup; + attack.isCrit = RollCrit(); + attack.damageType = DamageType.Stun1s; + attack.damageColorIndex = DamageColorIndex.Void; + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(base.characterBody.teamComponent.teamIndex); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.minDistanceFilter = 0f; + bullseyeSearch.maxDistanceFilter = searchMaxDistance; + bullseyeSearch.searchOrigin = base.inputBank.aimOrigin; + bullseyeSearch.searchDirection = base.inputBank.aimDirection; + bullseyeSearch.maxAngleFilter = searchMaxAngle; + bullseyeSearch.filterByLoS = true; + bullseyeSearch.RefreshCandidates(); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)hurtBox) + { + targetTransform = hurtBox.transform; + if ((bool)base.characterMotor) + { + Vector3 position = targetTransform.position; + float num = velocityInitialSpeed; + Vector3 vector = position - base.transform.position; + Vector2 vector2 = new Vector2(vector.x, vector.z); + float magnitude = vector2.magnitude; + float y = Trajectory.CalculateInitialYSpeed(magnitude / num, vector.y); + Vector3 vector3 = new Vector3(vector2.x / magnitude * num, y, vector2.y / magnitude * num); + base.characterMotor.velocity = vector3; + base.characterMotor.disableAirControlUntilCollision = true; + base.characterMotor.Motor.ForceUnground(); + base.characterDirection.forward = vector3; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)targetTransform && (bool)base.characterMotor) + { + Vector3 target = targetTransform.position - base.transform.position; + Vector3 velocity = base.characterMotor.velocity; + velocity = Vector3.RotateTowards(velocity, target, velocityTurnRate * GetDeltaTime() * (MathF.PI / 180f), 0f); + base.characterMotor.velocity = velocity; + if (NetworkServer.active && attack.Fire(victimsStruck)) + { + for (int i = 0; i < victimsStruck.Count; i++) + { + HealthComponent obj = victimsStruck[i].healthComponent; + CharacterBody body = obj.body; + CharacterMaster master = body.master; + if (obj.alive && master != null && !body.isPlayerControlled && !body.bodyFlags.HasFlag(CharacterBody.BodyFlags.Mechanical)) + { + master.teamIndex = TeamIndex.Void; + body.teamComponent.teamIndex = TeamIndex.Void; + body.inventory.SetEquipmentIndex(DLC1Content.Elites.Void.eliteEquipmentDef.equipmentIndex); + BaseAI component = master.GetComponent(); + if ((bool)component) + { + component.enemyAttention = 0f; + component.ForceAcquireNearestEnemyIfNoCurrentEnemy(); + } + base.healthComponent.Suicide(); + if ((bool)successfulInfestEffectPrefab) + { + EffectManager.SimpleImpactEffect(successfulInfestEffectPrefab, base.transform.position, Vector3.up, transmit: false); + } + break; + } + } + } + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterMotor.velocity; + } + if (base.isAuthority && (bool)base.characterMotor && base.characterMotor.isGrounded && base.fixedAge > 0.1f) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)infestVfxInstance) + { + EntityState.Destroy(infestVfxInstance); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Spawn.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Spawn.cs new file mode 100644 index 0000000..a7d155f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidInfestor/Spawn.cs @@ -0,0 +1,40 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidInfestor; + +public class Spawn : BaseState +{ + public static GameObject spawnEffectPrefab; + + public static float velocityStrength; + + public static float spread; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleImpactEffect(spawnEffectPrefab, base.characterBody.corePosition, Vector3.up, transmit: false); + } + if ((bool)base.characterMotor) + { + Vector3 vector = (Vector3.up + Random.onUnitSphere * spread) * velocityStrength; + base.characterMotor.ApplyForce(vector, alwaysApply: true, disableAirControlUntilCollision: true); + base.characterDirection.forward = vector; + } + PlayAnimation("Base", SpawnStateHash); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)base.characterMotor && base.characterMotor.isGrounded && base.fixedAge > 0.1f) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/Capture2.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/Capture2.cs new file mode 100644 index 0000000..bf34ce3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/Capture2.cs @@ -0,0 +1,157 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidJailer.Weapon; + +public class Capture2 : BaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateName; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public float pullFieldOfView; + + [SerializeField] + public float pullMinDistance; + + [SerializeField] + public float pullMaxDistance; + + [SerializeField] + public AnimationCurve pullSuitabilityCurve; + + [SerializeField] + public GameObject pullTracerPrefab; + + [SerializeField] + public float pullLiftVelocity; + + [SerializeField] + public BuffDef debuffDef; + + [SerializeField] + public float debuffDuration; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public string muzzleString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + Ray aimRay = GetAimRay(); + if (!NetworkServer.active) + { + return; + } + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.all; + bullseyeSearch.maxAngleFilter = pullFieldOfView * 0.5f; + bullseyeSearch.maxDistanceFilter = pullMaxDistance; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.filterByLoS = true; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + GetTeam(); + if (!hurtBox) + { + return; + } + Vector3 vector = hurtBox.transform.position - aimRay.origin; + float magnitude = vector.magnitude; + Vector3 vector2 = vector / magnitude; + float num = 1f; + CharacterBody body = hurtBox.healthComponent.body; + if ((bool)body.characterMotor) + { + num = body.characterMotor.mass; + } + else if ((bool)hurtBox.healthComponent.GetComponent()) + { + num = base.rigidbody.mass; + } + if ((bool)debuffDef) + { + body.AddTimedBuff(debuffDef, debuffDuration); + } + float num2 = pullSuitabilityCurve.Evaluate(num); + Vector3 vector3 = vector2; + float num3 = Trajectory.CalculateInitialYSpeedForHeight(Mathf.Abs(pullMinDistance - magnitude)) * Mathf.Sign(pullMinDistance - magnitude); + vector3 *= num3; + vector3.y = pullLiftVelocity; + DamageInfo damageInfo = new DamageInfo + { + attacker = base.gameObject, + damage = damageStat * damageCoefficient, + position = hurtBox.transform.position, + procCoefficient = procCoefficient + }; + hurtBox.healthComponent.TakeDamageForce(vector3 * (num * num2), alwaysApply: true, disableAirControlUntilCollision: true); + hurtBox.healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, hurtBox.healthComponent.gameObject); + if ((bool)pullTracerPrefab) + { + Vector3 position = hurtBox.transform.position; + Vector3 start = base.characterBody.corePosition; + Transform transform = FindModelChild(muzzleString); + if ((bool)transform) + { + start = transform.position; + } + EffectData effectData = new EffectData + { + origin = position, + start = start + }; + EffectManager.SpawnEffect(pullTracerPrefab, effectData, transmit: true); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextState(new ExitCapture()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ChargeCapture.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ChargeCapture.cs new file mode 100644 index 0000000..338fd12 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ChargeCapture.cs @@ -0,0 +1,83 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidJailer.Weapon; + +public class ChargeCapture : BaseState +{ + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static float duration; + + public static string enterSoundString; + + public static GameObject chargeEffectPrefab; + + public static GameObject attackIndicatorPrefab; + + public static string muzzleString; + + private float _crossFadeDuration; + + private uint soundID; + + private GameObject attackIndicatorInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration /= attackSpeedStat; + _crossFadeDuration = duration * 0.25f; + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateName, duration, _crossFadeDuration); + soundID = Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + if ((bool)chargeEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(chargeEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + if ((bool)attackIndicatorPrefab) + { + Transform coreTransform = base.characterBody.coreTransform; + if ((bool)coreTransform) + { + attackIndicatorInstance = Object.Instantiate(attackIndicatorPrefab, coreTransform); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new Capture2()); + } + } + + public override void Update() + { + if ((bool)attackIndicatorInstance) + { + attackIndicatorInstance.transform.forward = GetAimRay().direction; + } + base.Update(); + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(soundID); + if ((bool)attackIndicatorInstance) + { + EntityState.Destroy(attackIndicatorInstance); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ChargeFire.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ChargeFire.cs new file mode 100644 index 0000000..f483175 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ChargeFire.cs @@ -0,0 +1,90 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidJailer.Weapon; + +public class ChargeFire : BaseState +{ + public static string attackSoundEffect; + + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static float baseDuration; + + public static GameObject chargeVfxPrefab; + + private float _totalDuration; + + private float _crossFadeDuration; + + private float _chargingDuration; + + private GameObject _chargeVfxInstance; + + public override void OnEnter() + { + base.OnEnter(); + _totalDuration = baseDuration / attackSpeedStat; + _crossFadeDuration = _totalDuration * 0.25f; + _chargingDuration = _totalDuration - _crossFadeDuration; + Transform modelTransform = GetModelTransform(); + Util.PlayAttackSpeedSound(attackSoundEffect, base.gameObject, attackSpeedStat); + if (modelTransform != null) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("ClawMuzzle"); + if ((bool)transform && (bool)chargeVfxPrefab) + { + _chargeVfxInstance = Object.Instantiate(chargeVfxPrefab, transform.position, transform.rotation, transform); + ScaleParticleSystemDuration component2 = _chargeVfxInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = _totalDuration; + } + } + } + } + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateName, _chargingDuration, _crossFadeDuration); + base.characterBody.SetAimTimer(_totalDuration + 3f); + } + + public override void Update() + { + base.Update(); + if ((bool)_chargeVfxInstance) + { + Ray aimRay = GetAimRay(); + _chargeVfxInstance.transform.forward = aimRay.direction; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= _totalDuration && base.isAuthority) + { + Fire nextState = new Fire(); + outer.SetNextState(nextState); + } + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)_chargeVfxInstance) + { + EntityState.Destroy(_chargeVfxInstance); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ExitCapture.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ExitCapture.cs new file mode 100644 index 0000000..d21ced5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/ExitCapture.cs @@ -0,0 +1,38 @@ +using RoR2; + +namespace EntityStates.VoidJailer.Weapon; + +public class ExitCapture : BaseState +{ + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static float duration; + + public static string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + duration /= attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/Fire.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/Fire.cs new file mode 100644 index 0000000..52cfbed --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer.Weapon/Fire.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +namespace EntityStates.VoidJailer.Weapon; + +public class Fire : GenericProjectileBaseState +{ + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static int totalProjectileCount; + + public static float maxRandomDistance; + + public static float basePriorityReductionDuration; + + private float priorityReductionDuration; + + private Transform muzzleTransform; + + public override void OnEnter() + { + muzzleTransform = FindModelChild("ClawMuzzle"); + base.OnEnter(); + base.characterBody.SetAimTimer(duration + 3f); + for (int i = 1; i < totalProjectileCount; i++) + { + FireProjectile(); + } + priorityReductionDuration = basePriorityReductionDuration / attackSpeedStat; + } + + protected override Ray ModifyProjectileAimRay(Ray aimRay) + { + aimRay.origin += Random.insideUnitSphere * maxRandomDistance; + return aimRay; + } + + protected override void PlayAnimation(float duration) + { + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + if (!(base.fixedAge > priorityReductionDuration)) + { + return InterruptPriority.PrioritySkill; + } + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/Capture.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/Capture.cs new file mode 100644 index 0000000..1f35286 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/Capture.cs @@ -0,0 +1,247 @@ +using System.Collections.Generic; +using System.Linq; +using EntityStates.VoidJailer.Weapon; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidJailer; + +public class Capture : BaseState +{ + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static GameObject chargeVfxPrefab; + + [SerializeField] + public float duration; + + public static GameObject tetherPrefab; + + public static GameObject captureRangeEffect; + + public static float effectScaleCoefficient; + + public static float effectScaleAddition; + + public static string muzzleName; + + public static string tetherOriginName; + + public static float maxTetherDistance; + + public static float tetherReelSpeed; + + public static float damagePerSecond; + + public static float damageTickFrequency; + + public static BuffDef tetherDebuff; + + public static float innerRange; + + public static BuffDef innerRangeDebuff; + + public static float innerRangeDebuffDuration; + + public static GameObject innerRangeDebuffEffect; + + public static bool singleDurationReset; + + public static string captureLoopSoundString; + + private Transform muzzleTransform; + + private List tetherControllers = new List(); + + private uint soundID; + + private bool initialized; + + private bool shouldModifyTetherDuration = true; + + private GameObject rangeEffect; + + private GameObject _chargeVfxInstance; + + public override void OnEnter() + { + muzzleTransform = FindModelChild(muzzleName); + if (NetworkServer.active) + { + InitializeTethers(); + } + if (NetworkServer.active && base.isAuthority && tetherControllers.Count == 0) + { + outer.SetNextState(new ExitCapture()); + return; + } + base.OnEnter(); + duration /= attackSpeedStat; + FireTethers(); + } + + private void InitializeTethers() + { + Vector3 position = muzzleTransform.position; + float breakDistanceSqr = maxTetherDistance * maxTetherDistance; + tetherControllers = new List(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = position; + bullseyeSearch.maxDistanceFilter = maxTetherDistance; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(base.teamComponent.teamIndex); + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.filterByLoS = true; + bullseyeSearch.searchDirection = Vector3.up; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + List list = bullseyeSearch.GetResults().ToList(); + for (int i = 0; i < list.Count; i++) + { + GameObject gameObject = list[i].healthComponent.gameObject; + if ((bool)gameObject && !TargetIsTethered(gameObject.GetComponent())) + { + GameObject obj = Object.Instantiate(tetherPrefab, position, Quaternion.identity, muzzleTransform); + JailerTetherController component = obj.GetComponent(); + component.NetworkownerRoot = base.gameObject; + component.Networkorigin = muzzleTransform.gameObject; + component.NetworktargetRoot = gameObject; + component.breakDistanceSqr = breakDistanceSqr; + component.damageCoefficientPerTick = damagePerSecond / damageTickFrequency; + component.tickInterval = 1f / damageTickFrequency; + component.tickTimer = (float)i * 0.1f; + component.NetworkreelSpeed = tetherReelSpeed; + component.SetTetheredBuff(tetherDebuff); + tetherControllers.Add(component); + NetworkServer.Spawn(obj); + } + } + initialized = true; + } + + private static bool TargetIsTethered(CharacterBody characterBody) + { + if (characterBody != null) + { + return characterBody.HasBuff(tetherDebuff); + } + return false; + } + + private void FireTethers() + { + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + soundID = Util.PlayAttackSpeedSound(captureLoopSoundString, base.gameObject, attackSpeedStat); + if (!muzzleTransform) + { + return; + } + if ((bool)captureRangeEffect) + { + rangeEffect = Object.Instantiate(captureRangeEffect, base.characterBody.transform); + rangeEffect.transform.localScale = effectScaleCoefficient * (maxTetherDistance + effectScaleAddition) * Vector3.one; + ScaleParticleSystemDuration component = rangeEffect.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + if ((bool)chargeVfxPrefab) + { + _chargeVfxInstance = Object.Instantiate(chargeVfxPrefab, muzzleTransform.position, muzzleTransform.rotation, muzzleTransform); + ScaleParticleSystemDuration component2 = _chargeVfxInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (initialized) + { + UpdateTethers(base.gameObject.transform.position); + if (tetherControllers.Count == 0 || base.fixedAge >= duration) + { + outer.SetNextState(new ExitCapture()); + } + } + } + + private void UpdateTethers(Vector3 origin) + { + for (int num = tetherControllers.Count - 1; num >= 0; num--) + { + JailerTetherController jailerTetherController = tetherControllers[num]; + if (!jailerTetherController) + { + tetherControllers.RemoveAt(num); + } + else + { + CharacterBody targetBody = jailerTetherController.GetTargetBody(); + if (!(targetBody == null) && !targetBody.HasBuff(innerRangeDebuff) && Vector3.Distance(origin, targetBody.transform.position) < innerRange) + { + float num2 = duration - base.fixedAge; + targetBody.AddTimedBuff(innerRangeDebuff, innerRangeDebuffDuration); + if (shouldModifyTetherDuration) + { + duration = ((num2 > innerRangeDebuffDuration) ? innerRangeDebuffDuration : (innerRangeDebuffDuration + base.fixedAge)); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, innerRangeDebuffDuration); + shouldModifyTetherDuration = !singleDurationReset; + if ((bool)_chargeVfxInstance) + { + ScaleParticleSystemDuration component = _chargeVfxInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + jailerTetherController.NetworkreelSpeed = 0f; + } + } + } + } + + public override void OnExit() + { + DestroyTethers(); + if ((bool)rangeEffect) + { + EntityState.Destroy(rangeEffect); + } + if ((bool)_chargeVfxInstance) + { + EntityState.Destroy(_chargeVfxInstance); + } + AkSoundEngine.StopPlayingID(soundID); + base.OnExit(); + } + + private void DestroyTethers() + { + if (tetherControllers == null) + { + return; + } + for (int num = tetherControllers.Count - 1; num >= 0; num--) + { + if ((bool)tetherControllers[num]) + { + EntityState.Destroy(tetherControllers[num].gameObject); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/CaptureFire.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/CaptureFire.cs new file mode 100644 index 0000000..456fe22 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/CaptureFire.cs @@ -0,0 +1,49 @@ +using RoR2; + +namespace EntityStates.VoidJailer; + +public class CaptureFire : BaseState +{ + public static string animationLayerName; + + public static string animationStateName; + + public static string animationPlaybackRateName; + + public static float duration; + + public static string enterSoundString; + + public static float exitCrossfadeDuration; + + public static string crossfadeStateName; + + public override void OnEnter() + { + base.OnEnter(); + duration /= attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateName, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + Capture nextState = new Capture(); + outer.SetNextState(nextState); + } + } + + public override void OnExit() + { + PlayCrossfade(animationLayerName, crossfadeStateName, animationPlaybackRateName, exitCrossfadeDuration, exitCrossfadeDuration); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/DeathState.cs new file mode 100644 index 0000000..e613240 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/DeathState.cs @@ -0,0 +1,59 @@ +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidJailer; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathBombProjectile; + + public static float duration; + + public static string muzzleName; + + private Transform muzzleTransform; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayCrossfade("Body", "Death", "Death.playbackRate", duration, 0.1f); + } + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + if ((bool)muzzleTransform && base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = deathBombProjectile; + fireProjectileInfo.position = muzzleTransform.position; + fireProjectileInfo.rotation = Quaternion.LookRotation(base.characterDirection.forward, Vector3.up); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat; + fireProjectileInfo.crit = base.characterBody.RollCrit(); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/SpawnState.cs new file mode 100644 index 0000000..f8ea7b4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidJailer/SpawnState.cs @@ -0,0 +1,25 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidJailer; + +public class SpawnState : GenericCharacterSpawnState +{ + public static GameObject spawnFXPrefab; + + public static string spawnFXTransformName; + + public override void OnEnter() + { + base.OnEnter(); + PlaySpawnFX(); + } + + private void PlaySpawnFX() + { + if (spawnFXPrefab != null && !string.IsNullOrEmpty(spawnFXTransformName)) + { + EffectManager.SimpleMuzzleFlash(spawnFXPrefab, base.gameObject, spawnFXTransformName, transmit: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.BackWeapon/FireVoidMissiles.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.BackWeapon/FireVoidMissiles.cs new file mode 100644 index 0000000..459aa2a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.BackWeapon/FireVoidMissiles.cs @@ -0,0 +1,92 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VoidMegaCrab.BackWeapon; + +public class FireVoidMissiles : BaseSkillState +{ + public static float baseDuration; + + public static string leftMuzzleString; + + public static string rightMuzzleString; + + public static GameObject muzzleEffectPrefab; + + public static GameObject projectilePrefab; + + public static int totalMissileWaveCount; + + public static float baseDurationBetweenMissiles; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string enterSoundString; + + public static string animationLayerName = "Gesture, Additive"; + + public static string animationStateName = "FireCrabCannon"; + + public static string animationPlaybackRateParam = "FireCrabCannon.playbackRate"; + + private float duration; + + private float durationBetweenMissiles; + + private float missileTimer; + + private int missileWaveCount; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + durationBetweenMissiles = baseDurationBetweenMissiles / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + private void FireMissile() + { + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, leftMuzzleString, transmit: false); + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, rightMuzzleString, transmit: false); + } + if (base.isAuthority) + { + Transform transform = FindModelChild(leftMuzzleString); + Transform transform2 = FindModelChild(rightMuzzleString); + Ray ray = GetAimRay(); + if (transform != null) + { + ray = new Ray(transform.position, transform.forward); + } + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + if (transform2 != null) + { + ray = new Ray(transform2.position, transform2.forward); + } + ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, Util.QuaternionSafeLookRotation(ray.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + missileTimer -= GetDeltaTime(); + if (missileWaveCount < totalMissileWaveCount && missileTimer <= 0f) + { + missileWaveCount++; + missileTimer += durationBetweenMissiles; + FireMissile(); + } + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabBlackCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabBlackCannon.cs new file mode 100644 index 0000000..66b173e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabBlackCannon.cs @@ -0,0 +1,9 @@ +namespace EntityStates.VoidMegaCrab.Weapon; + +public class ChargeCrabBlackCannon : ChargeCrabCannonBase +{ + protected override FireCrabCannonBase GetNextState() + { + return new FireCrabBlackCannon(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabCannonBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabCannonBase.cs new file mode 100644 index 0000000..ed26b58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabCannonBase.cs @@ -0,0 +1,95 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidMegaCrab.Weapon; + +public abstract class ChargeCrabCannonBase : BaseState +{ + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public string soundName; + + [SerializeField] + public string chargeMuzzleName; + + [SerializeField] + public string animationLayerName = "Gesture, Additive"; + + [SerializeField] + public string animationStateName = "FireCrabCannon"; + + [SerializeField] + public string animationStateNamePreCharged = "FireCrabCannon"; + + [SerializeField] + public string animationPlaybackRateParam = "FireCrabCannon.playbackRate"; + + [SerializeField] + public float animationCrossfadeDuration = 0.2f; + + private GameObject chargeInstance; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex(animationLayerName); + if (modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).IsName("Empty")) + { + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateParam, duration, animationCrossfadeDuration); + } + else + { + PlayCrossfade(animationLayerName, animationStateNamePreCharged, animationPlaybackRateParam, duration, animationCrossfadeDuration); + } + } + Util.PlaySound(soundName, base.gameObject); + Transform transform = FindModelChild(chargeMuzzleName); + if ((bool)chargeEffectPrefab && (bool)transform) + { + chargeInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + base.characterBody.SetAimTimer(duration + 2f); + } + + public override void OnExit() + { + base.OnExit(); + if ((bool)chargeInstance) + { + EntityState.Destroy(chargeInstance); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextState(GetNextState()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected abstract FireCrabCannonBase GetNextState(); +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabWhiteCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabWhiteCannon.cs new file mode 100644 index 0000000..824666f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/ChargeCrabWhiteCannon.cs @@ -0,0 +1,9 @@ +namespace EntityStates.VoidMegaCrab.Weapon; + +public class ChargeCrabWhiteCannon : ChargeCrabCannonBase +{ + protected override FireCrabCannonBase GetNextState() + { + return new FireCrabWhiteCannon(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabBlackCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabBlackCannon.cs new file mode 100644 index 0000000..233dc90 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabBlackCannon.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidMegaCrab.Weapon; + +public class FireCrabBlackCannon : FireCrabCannonBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabCannonBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabCannonBase.cs new file mode 100644 index 0000000..1774af1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabCannonBase.cs @@ -0,0 +1,122 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VoidMegaCrab.Weapon; + +public class FireCrabCannonBase : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public int projectileCount = 3; + + [SerializeField] + public float spread; + + [SerializeField] + public float bonusPitch; + + [SerializeField] + public float totalYawSpread = 5f; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float baseFireDuration = 0.2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackSound; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string animationLayerName = "Gesture, Additive"; + + [SerializeField] + public string animationStateName = "FireCrabCannon"; + + [SerializeField] + public string animationPlaybackRateParam = "FireCrabCannon.playbackRate"; + + private float duration; + + private float fireDuration; + + private int projectilesFired; + + private Transform muzzleTransform; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + fireDuration = baseFireDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + muzzleTransform = FindModelChild(muzzleName); + if (!muzzleTransform) + { + muzzleTransform = base.characterBody.aimOriginTransform; + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + int num = Mathf.FloorToInt(base.fixedAge / fireDuration * (float)projectileCount); + if (projectilesFired <= num && projectilesFired < projectileCount) + { + FireProjectile(); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + private void FireProjectile() + { + Util.PlaySound(attackSound, base.gameObject); + base.characterBody.SetAimTimer(3f); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + int num = Mathf.FloorToInt((float)projectilesFired - (float)(projectileCount - 1) / 2f); + float bonusYaw = 0f; + if (projectileCount > 1) + { + bonusYaw = (float)num / (float)(projectileCount - 1) * totalYawSpread; + } + Vector3 forward = Util.ApplySpread(aimRay.direction, 0f, spread, 1f, 1f, bonusYaw, bonusPitch); + Vector3 position = muzzleTransform.position; + ProjectileManager.instance.FireProjectile(projectilePrefab, position, Util.QuaternionSafeLookRotation(forward), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + projectilesFired++; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabWhiteCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabWhiteCannon.cs new file mode 100644 index 0000000..2b4d0a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab.Weapon/FireCrabWhiteCannon.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidMegaCrab.Weapon; + +public class FireCrabWhiteCannon : FireCrabCannonBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab/DeathState.cs new file mode 100644 index 0000000..a6e56b6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab/DeathState.cs @@ -0,0 +1,68 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidMegaCrab; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject deathBombProjectile; + + public static float duration; + + public static string muzzleName; + + private Transform muzzleTransform; + + private static int EmptyStateHash = Animator.StringToHash("Empty"); + + private static int DeathStateHash = Animator.StringToHash("Death"); + + private static int DeathParamHash = Animator.StringToHash("Death.playbackRate"); + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + PlayCrossfade("Body", DeathStateHash, DeathParamHash, duration, 0.1f); + PlayAnimation("Left Gun Override (Arm)", EmptyStateHash); + PlayAnimation("Right Gun Override (Arm)", EmptyStateHash); + } + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + if ((bool)muzzleTransform && base.isAuthority) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = deathBombProjectile; + fireProjectileInfo.position = muzzleTransform.position; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(Vector3.up); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat; + fireProjectileInfo.crit = base.characterBody.RollCrit(); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + DestroyModel(); + if (NetworkServer.active) + { + DestroyBodyAsapServer(); + } + } + } + + public override void OnExit() + { + DestroyModel(); + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab/SpawnState.cs new file mode 100644 index 0000000..f217ef0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidMegaCrab/SpawnState.cs @@ -0,0 +1,58 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidMegaCrab; + +public class SpawnState : BaseState +{ + [SerializeField] + public float duration = 4f; + + [SerializeField] + public string spawnSoundString; + + [SerializeField] + public GameObject spawnEffectPrefab; + + [SerializeField] + public string spawnMuzzleName; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnMuzzleName, transmit: false); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + modelTransform.GetComponent().enabled = true; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Joint/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Joint/DeathState.cs new file mode 100644 index 0000000..5c7ebf7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Joint/DeathState.cs @@ -0,0 +1,53 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Joint; + +public class DeathState : GenericCharacterDeath +{ + [SerializeField] + public string joint1Name; + + [SerializeField] + public string joint2Name; + + [SerializeField] + public string joint3Name; + + [SerializeField] + public GameObject joint1EffectPrefab; + + [SerializeField] + public GameObject joint2EffectPrefab; + + [SerializeField] + public GameObject joint3EffectPrefab; + + private CharacterModel characterModel; + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleMuzzleFlash(joint1EffectPrefab, base.gameObject, joint1Name, transmit: false); + EffectManager.SimpleMuzzleFlash(joint2EffectPrefab, base.gameObject, joint2Name, transmit: false); + EffectManager.SimpleMuzzleFlash(joint3EffectPrefab, base.gameObject, joint3Name, transmit: false); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + } + + public override void OnExit() + { + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Joint/PreDeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Joint/PreDeathState.cs new file mode 100644 index 0000000..a8c890d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Joint/PreDeathState.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Joint; + +public class PreDeathState : BaseState +{ + [SerializeField] + public float minDuration; + + [SerializeField] + public string joint1Name; + + [SerializeField] + public string joint2Name; + + [SerializeField] + public string joint3Name; + + [SerializeField] + public GameObject jointEffectPrefab; + + public bool canProceed; + + private List jointEffects = new List(); + + public override void OnEnter() + { + base.OnEnter(); + canProceed = false; + jointEffects.Clear(); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + SpawnJointEffect(joint1Name, modelChildLocator); + SpawnJointEffect(joint2Name, modelChildLocator); + SpawnJointEffect(joint3Name, modelChildLocator); + } + } + + public override void OnExit() + { + base.OnExit(); + foreach (GameObject jointEffect in jointEffects) + { + Object.Destroy(jointEffect); + } + jointEffects.Clear(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > minDuration && canProceed) + { + outer.SetNextState(new DeathState()); + } + } + + private void SpawnJointEffect(string jointName, ChildLocator childLocator) + { + Transform transform = childLocator.FindChild(jointName); + if ((bool)transform) + { + GameObject item = Object.Instantiate(jointEffectPrefab, transform); + jointEffects.Add(item); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/BaseLegState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/BaseLegState.cs new file mode 100644 index 0000000..70ba123 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/BaseLegState.cs @@ -0,0 +1,23 @@ +using RoR2.VoidRaidCrab; + +namespace EntityStates.VoidRaidCrab.Leg; + +public class BaseLegState : EntityState +{ + protected LegController legController { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + legController = legController ?? GetComponent(); + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is BaseLegState baseLegState) + { + baseLegState.legController = legController; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/BaseStompState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/BaseStompState.cs new file mode 100644 index 0000000..0ec84b3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/BaseStompState.cs @@ -0,0 +1,111 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Leg; + +public abstract class BaseStompState : BaseLegState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string animName; + + public static GameObject warningIndicatorPrefab; + + public GameObject target; + + protected float duration; + + private bool lifetimeExpiredAuthority; + + private RayAttackIndicator warningIndicatorInstance; + + protected virtual bool shouldUseWarningIndicator => false; + + protected virtual bool shouldUpdateLegStompTargetPosition => false; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + string stompPlaybackRateParam = base.legController.stompPlaybackRateParam; + if (!string.IsNullOrEmpty(stompPlaybackRateParam)) + { + EntityState.PlayAnimationOnAnimator(base.legController.animator, base.legController.primaryLayerName, animName, stompPlaybackRateParam, duration); + } + else + { + EntityState.PlayAnimationOnAnimator(base.legController.animator, base.legController.primaryLayerName, animName); + int layerIndex = base.legController.animator.GetLayerIndex(base.legController.primaryLayerName); + duration = base.legController.animator.GetCurrentAnimatorStateInfo(layerIndex).length; + } + SetWarningIndicatorActive(shouldUseWarningIndicator); + } + + public override void OnExit() + { + SetWarningIndicatorActive(newWarningIndicatorActive: false); + base.OnExit(); + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is BaseStompState baseStompState) + { + baseStompState.warningIndicatorInstance = warningIndicatorInstance; + warningIndicatorInstance = null; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.legController.mainBody.hasEffectiveAuthority && base.fixedAge >= duration && !lifetimeExpiredAuthority) + { + lifetimeExpiredAuthority = true; + OnLifetimeExpiredAuthority(); + } + if (shouldUpdateLegStompTargetPosition && (bool)target) + { + base.legController.SetStompTargetWorldPosition(target.transform.position); + } + UpdateWarningIndicatorInstance(); + } + + protected abstract void OnLifetimeExpiredAuthority(); + + protected void SetWarningIndicatorActive(bool newWarningIndicatorActive) + { + if ((bool)warningIndicatorInstance == newWarningIndicatorActive) + { + return; + } + if (newWarningIndicatorActive) + { + GameObject gameObject = Object.Instantiate(warningIndicatorPrefab); + warningIndicatorInstance = gameObject.GetComponent(); + UpdateWarningIndicatorInstance(); + return; + } + if ((bool)warningIndicatorInstance) + { + EntityState.Destroy(warningIndicatorInstance.gameObject); + } + warningIndicatorInstance = null; + } + + private void UpdateWarningIndicatorInstance() + { + if ((bool)warningIndicatorInstance) + { + Vector3 position = base.legController.toeTipTransform.position; + Vector3 vector = (base.legController.mainBody ? base.legController.mainBody.transform.position : position); + warningIndicatorInstance.attackRay = new Ray(position, Vector3.down); + warningIndicatorInstance.attackRange = position.y - vector.y; + warningIndicatorInstance.attackRadius = Stomp.blastRadius; + warningIndicatorInstance.layerMask = LayerIndex.world.mask; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Idle.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Idle.cs new file mode 100644 index 0000000..7717a33 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Idle.cs @@ -0,0 +1,13 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class Idle : BaseLegState +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.legController.mainBodyHasEffectiveAuthority && !base.legController.DoesJointExist()) + { + outer.SetNextState(new JointBroken()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/JointBroken.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/JointBroken.cs new file mode 100644 index 0000000..0201169 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/JointBroken.cs @@ -0,0 +1,25 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class JointBroken : BaseLegState +{ + public override void OnEnter() + { + base.OnEnter(); + base.legController.shouldRetract = true; + } + + public override void OnExit() + { + base.OnExit(); + base.legController.shouldRetract = false; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.legController.mainBodyHasEffectiveAuthority && base.legController.DoesJointExist()) + { + outer.SetNextState(new Idle()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PostStompReturnToBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PostStompReturnToBase.cs new file mode 100644 index 0000000..9b9773d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PostStompReturnToBase.cs @@ -0,0 +1,9 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class PostStompReturnToBase : BaseStompState +{ + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompFollowTarget.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompFollowTarget.cs new file mode 100644 index 0000000..17014c0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompFollowTarget.cs @@ -0,0 +1,16 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class PreStompFollowTarget : BaseStompState +{ + protected override bool shouldUseWarningIndicator => true; + + protected override bool shouldUpdateLegStompTargetPosition => true; + + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new PreStompPauseBeforeStomp + { + target = target + }); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompLegRaise.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompLegRaise.cs new file mode 100644 index 0000000..7b0cd2d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompLegRaise.cs @@ -0,0 +1,16 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class PreStompLegRaise : BaseStompState +{ + protected override bool shouldUseWarningIndicator => true; + + protected override bool shouldUpdateLegStompTargetPosition => true; + + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new PreStompFollowTarget + { + target = target + }); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompPauseBeforeStomp.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompPauseBeforeStomp.cs new file mode 100644 index 0000000..afd4fa2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/PreStompPauseBeforeStomp.cs @@ -0,0 +1,12 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class PreStompPauseBeforeStomp : BaseStompState +{ + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new Stomp + { + target = target + }); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Restore.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Restore.cs new file mode 100644 index 0000000..a3fe4dc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Restore.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class Restore : BaseLegState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Retract.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Retract.cs new file mode 100644 index 0000000..51879a1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Retract.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class Retract : BaseLegState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Retracted.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Retracted.cs new file mode 100644 index 0000000..855de8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Retracted.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidRaidCrab.Leg; + +public class Retracted : BaseLegState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Stomp.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Stomp.cs new file mode 100644 index 0000000..ee7be4d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Leg/Stomp.cs @@ -0,0 +1,123 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Leg; + +public class Stomp : BaseStompState +{ + public static float blastDamageCoefficient; + + public static float blastRadius; + + public static float blastForce; + + public static GameObject blastEffectPrefab; + + private Vector3? previousToePosition; + + private bool hasDoneBlast; + + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new PostStompReturnToBase + { + target = target + }); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!hasDoneBlast && (bool)base.legController.mainBody && base.legController.mainBody.hasEffectiveAuthority) + { + TryStompCollisionAuthority(); + } + } + + private void TryStompCollisionAuthority() + { + Vector3 currentToePosition = base.legController.toeTipTransform.position; + TryAttack(); + previousToePosition = currentToePosition; + void TryAttack() + { + if (previousToePosition.HasValue) + { + Vector3 value = previousToePosition.Value; + if (!((currentToePosition - value).sqrMagnitude < 0.0025000002f) && Physics.Linecast(previousToePosition.Value, currentToePosition, out var hitInfo, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + DoBlastAuthority(hitInfo.point); + base.legController.DoToeConcussionBlastAuthority(hitInfo.point, useEffect: false); + hasDoneBlast = true; + } + } + } + } + + private void DoBlastAuthority(Vector3 blastOrigin) + { + CharacterBody mainBody = base.legController.mainBody; + EffectData effectData = new EffectData(); + effectData.origin = blastOrigin; + effectData.scale = blastRadius; + effectData.rotation = Quaternion.LookRotation(Vector3.up); + EffectManager.SpawnEffect(blastEffectPrefab, effectData, transmit: true); + BlastAttack obj = new BlastAttack + { + attacker = mainBody.gameObject + }; + obj.inflictor = obj.attacker; + obj.baseDamage = blastDamageCoefficient * mainBody.damage; + obj.baseForce = blastForce; + obj.position = blastOrigin; + obj.radius = blastRadius; + obj.falloffModel = BlastAttack.FalloffModel.SweetSpot; + obj.teamIndex = mainBody.teamComponent.teamIndex; + obj.attackerFiltering = AttackerFiltering.NeverHitSelf; + obj.damageType = DamageType.Generic; + obj.crit = mainBody.RollCrit(); + obj.damageColorIndex = DamageColorIndex.Default; + obj.impactEffect = EffectIndex.Invalid; + obj.losType = BlastAttack.LoSType.None; + obj.procChainMask = default(ProcChainMask); + obj.procCoefficient = 1f; + obj.Fire(); + } + + private void DoStompAttackAuthority(Vector3 hitPosition) + { + CharacterBody mainBody = base.legController.mainBody; + if ((bool)mainBody) + { + Vector3 position = base.legController.footTranform.position; + Vector3 position2 = base.legController.toeTipTransform.position; + RaycastHit hitInfo; + Vector3 vector = (Physics.Linecast(position, position2, out hitInfo, LayerIndex.world.mask, QueryTriggerInteraction.Ignore) ? hitInfo.point : position2); + EffectData effectData = new EffectData(); + effectData.origin = vector; + effectData.scale = blastRadius; + effectData.rotation = Quaternion.LookRotation(-hitInfo.normal); + EffectManager.SpawnEffect(blastEffectPrefab, effectData, transmit: true); + BlastAttack obj = new BlastAttack + { + attacker = mainBody.gameObject + }; + obj.inflictor = obj.attacker; + obj.baseDamage = blastDamageCoefficient * mainBody.damage; + obj.baseForce = blastForce; + obj.position = vector; + obj.radius = blastRadius; + obj.falloffModel = BlastAttack.FalloffModel.Linear; + obj.teamIndex = mainBody.teamComponent.teamIndex; + obj.attackerFiltering = AttackerFiltering.NeverHitSelf; + obj.damageType = DamageType.Generic; + obj.crit = mainBody.RollCrit(); + obj.damageColorIndex = DamageColorIndex.Default; + obj.impactEffect = EffectIndex.Invalid; + obj.losType = BlastAttack.LoSType.None; + obj.procChainMask = default(ProcChainMask); + obj.procCoefficient = 1f; + obj.Fire(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseFireMultiBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseFireMultiBeam.cs new file mode 100644 index 0000000..aaa3d03 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseFireMultiBeam.cs @@ -0,0 +1,117 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public abstract class BaseFireMultiBeam : BaseMultiBeamState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public GameObject muzzleEffectPrefab; + + [SerializeField] + public GameObject tracerEffectPrefab; + + [SerializeField] + public GameObject explosionEffectPrefab; + + [SerializeField] + public float blastDamageCoefficient; + + [SerializeField] + public float blastForceMagnitude; + + [SerializeField] + public float blastRadius; + + [SerializeField] + public Vector3 blastBonusForce; + + [SerializeField] + public string enterSoundString; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Transform modelTransform = GetModelTransform(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, BaseMultiBeamState.muzzleName, transmit: false); + } + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + if (!base.isAuthority) + { + return; + } + CalcBeamPath(out var beamRay, out var beamEndPos); + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = base.gameObject; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(base.gameObject); + blastAttack.baseDamage = damageStat * blastDamageCoefficient; + blastAttack.baseForce = blastForceMagnitude; + blastAttack.position = beamEndPos; + blastAttack.radius = blastRadius; + blastAttack.falloffModel = BlastAttack.FalloffModel.SweetSpot; + blastAttack.bonusForce = blastBonusForce; + blastAttack.damageType = DamageType.Generic; + blastAttack.Fire(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + int childIndex = component.FindChildIndex(BaseMultiBeamState.muzzleName); + if ((bool)tracerEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = beamEndPos, + start = beamRay.origin, + scale = blastRadius + }; + effectData.SetChildLocatorTransformReference(base.gameObject, childIndex); + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + EffectManager.SpawnEffect(explosionEffectPrefab, effectData, transmit: true); + } + } + } + OnFireBeam(beamRay.origin, beamEndPos); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + EntityState nextState = InstantiateNextState(); + outer.SetNextState(nextState); + } + } + + protected abstract EntityState InstantiateNextState(); + + protected virtual void OnFireBeam(Vector3 beamStart, Vector3 beamEnd) + { + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseGravityBumpState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseGravityBumpState.cs new file mode 100644 index 0000000..618969c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseGravityBumpState.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public abstract class BaseGravityBumpState : BaseState +{ + [SerializeField] + public float maxDistance; + + protected Vector3 airborneForce; + + protected Vector3 groundedForce; + + protected bool isLeft; + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(isLeft); + writer.Write(groundedForce); + writer.Write(airborneForce); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + isLeft = reader.ReadBoolean(); + groundedForce = reader.ReadVector3(); + airborneForce = reader.ReadVector3(); + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is BaseGravityBumpState baseGravityBumpState) + { + baseGravityBumpState.groundedForce = groundedForce; + baseGravityBumpState.airborneForce = airborneForce; + baseGravityBumpState.isLeft = isLeft; + } + } + + protected IEnumerable GetTargets() + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(base.characterBody.teamComponent.teamIndex); + bullseyeSearch.minDistanceFilter = 0f; + bullseyeSearch.maxDistanceFilter = maxDistance; + bullseyeSearch.searchOrigin = base.inputBank.aimOrigin; + bullseyeSearch.searchDirection = base.inputBank.aimDirection; + bullseyeSearch.maxAngleFilter = 360f; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.filterByDistinctEntity = true; + bullseyeSearch.RefreshCandidates(); + return bullseyeSearch.GetResults(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseMultiBeamState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseMultiBeamState.cs new file mode 100644 index 0000000..7824fa4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/BaseMultiBeamState.cs @@ -0,0 +1,40 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public abstract class BaseMultiBeamState : BaseState +{ + public static float beamMaxDistance = 1000f; + + public static string muzzleName; + + protected Transform muzzleTransform { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + muzzleTransform = FindModelChild(muzzleName); + } + + protected void CalcBeamPath(out Ray beamRay, out Vector3 beamEndPos) + { + Ray aimRay = GetAimRay(); + float num = float.PositiveInfinity; + RaycastHit[] array = Physics.RaycastAll(aimRay, beamMaxDistance, LayerIndex.CommonMasks.bullet, QueryTriggerInteraction.Ignore); + Transform root = GetModelTransform().root; + for (int i = 0; i < array.Length; i++) + { + ref RaycastHit reference = ref array[i]; + float distance = reference.distance; + if (distance < num && (object)reference.collider.transform.root != root) + { + num = distance; + } + } + num = Mathf.Min(num, beamMaxDistance); + beamEndPos = aimRay.GetPoint(num); + Vector3 position = muzzleTransform.position; + beamRay = new Ray(position, beamEndPos - position); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeGravityBump.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeGravityBump.cs new file mode 100644 index 0000000..2d7144d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeGravityBump.cs @@ -0,0 +1,171 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class ChargeGravityBump : BaseGravityBumpState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public bool isSoundScaledByAttackSpeed; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public float horizontalAirborneForce; + + [SerializeField] + public float verticalAirborneForce; + + [SerializeField] + public float horizontalGroundedForce; + + [SerializeField] + public float verticalGroundedForce; + + [SerializeField] + public GameObject forceIndicatorPrefab; + + private float duration; + + private GameObject chargeEffectInstance; + + private Dictionary characterMotorsToIndicatorTransforms; + + private Quaternion airborneForceOrientation; + + private Quaternion groundedForceOrientation; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + isLeft = Random.value > 0.5f; + CharacterDirection component = GetComponent(); + if ((bool)component) + { + Vector3 vector = Vector3.Cross(component.forward, Vector3.up); + if (!isLeft) + { + vector *= -1f; + } + airborneForce = Vector3.up * -1f * verticalAirborneForce + vector * horizontalAirborneForce; + groundedForce = Vector3.up * verticalGroundedForce + vector * horizontalGroundedForce; + } + } + airborneForceOrientation = Util.QuaternionSafeLookRotation(airborneForce); + groundedForceOrientation = Util.QuaternionSafeLookRotation(groundedForce); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && (bool)chargeEffectPrefab) + { + Transform transform = modelChildLocator.FindChild(muzzleName) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffectInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + } + if (!string.IsNullOrEmpty(enterSoundString)) + { + if (isSoundScaledByAttackSpeed) + { + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + } + else + { + Util.PlaySound(enterSoundString, base.gameObject); + } + } + characterMotorsToIndicatorTransforms = new Dictionary(); + AssignIndicators(); + } + + public override void OnExit() + { + CleanUpIndicators(); + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + foreach (KeyValuePair characterMotorsToIndicatorTransform in characterMotorsToIndicatorTransforms) + { + if (characterMotorsToIndicatorTransform.Key.isGrounded) + { + characterMotorsToIndicatorTransform.Value.rotation = groundedForceOrientation; + } + else + { + characterMotorsToIndicatorTransform.Value.rotation = airborneForceOrientation; + } + } + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new FireGravityBump()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private void AssignIndicators() + { + foreach (HurtBox target in GetTargets()) + { + GameObject gameObject = target.healthComponent.gameObject; + if ((bool)gameObject) + { + CharacterMotor component = gameObject.GetComponent(); + if ((bool)component && !characterMotorsToIndicatorTransforms.ContainsKey(component)) + { + GameObject gameObject2 = Object.Instantiate(forceIndicatorPrefab, gameObject.transform); + characterMotorsToIndicatorTransforms.Add(component, gameObject2.transform); + } + } + } + } + + private void CleanUpIndicators() + { + foreach (KeyValuePair characterMotorsToIndicatorTransform in characterMotorsToIndicatorTransforms) + { + Transform value = characterMotorsToIndicatorTransform.Value; + if ((bool)value) + { + EntityState.Destroy(value.gameObject); + } + } + characterMotorsToIndicatorTransforms.Clear(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeMissiles.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeMissiles.cs new file mode 100644 index 0000000..a3d605a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeMissiles.cs @@ -0,0 +1,83 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class ChargeMissiles : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public bool isSoundScaledByAttackSpeed; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && (bool)chargeEffectPrefab) + { + Transform transform = modelChildLocator.FindChild(muzzleName) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + } + } + if (!string.IsNullOrEmpty(enterSoundString)) + { + if (isSoundScaledByAttackSpeed) + { + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + } + else + { + Util.PlaySound(enterSoundString, base.gameObject); + } + } + } + + public override void OnExit() + { + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new FireMissiles()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeMultiBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeMultiBeam.cs new file mode 100644 index 0000000..bef7457 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/ChargeMultiBeam.cs @@ -0,0 +1,143 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class ChargeMultiBeam : BaseMultiBeamState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public GameObject warningLaserVfxPrefab; + + [SerializeField] + public new string muzzleName; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public bool isSoundScaledByAttackSpeed; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + private GameObject chargeEffectInstance; + + private GameObject warningLaserVfxInstance; + + private RayAttackIndicator warningLaserVfxInstanceRayAttackIndicator; + + private bool warningLaserEnabled + { + get + { + return warningLaserVfxInstance; + } + set + { + if (value == warningLaserEnabled) + { + return; + } + if (value) + { + if ((bool)warningLaserVfxPrefab) + { + warningLaserVfxInstance = Object.Instantiate(warningLaserVfxPrefab); + warningLaserVfxInstanceRayAttackIndicator = warningLaserVfxInstance.GetComponent(); + UpdateWarningLaser(); + } + } + else + { + EntityState.Destroy(warningLaserVfxInstance); + warningLaserVfxInstance = null; + warningLaserVfxInstanceRayAttackIndicator = null; + } + } + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && (bool)chargeEffectPrefab) + { + Transform transform = modelChildLocator.FindChild(muzzleName) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + if (!string.IsNullOrEmpty(enterSoundString)) + { + if (isSoundScaledByAttackSpeed) + { + Util.PlayAttackSpeedSound(enterSoundString, base.gameObject, attackSpeedStat); + } + else + { + Util.PlaySound(enterSoundString, base.gameObject); + } + } + warningLaserEnabled = true; + } + + public override void OnExit() + { + warningLaserEnabled = false; + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new FireMultiBeamSmall()); + } + } + + public override void Update() + { + base.Update(); + UpdateWarningLaser(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + private void UpdateWarningLaser() + { + if ((bool)warningLaserVfxInstanceRayAttackIndicator) + { + warningLaserVfxInstanceRayAttackIndicator.attackRange = BaseMultiBeamState.beamMaxDistance; + CalcBeamPath(out var beamRay, out var _); + warningLaserVfxInstanceRayAttackIndicator.attackRay = beamRay; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireGravityBump.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireGravityBump.cs new file mode 100644 index 0000000..ed74c40 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireGravityBump.cs @@ -0,0 +1,144 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class FireGravityBump : BaseGravityBumpState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public bool disableAirControlUntilCollision; + + [SerializeField] + public GameObject airborneEffectPrefab; + + [SerializeField] + public GameObject groundedEffectPrefab; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public bool isSoundScaledByAttackSpeed; + + [SerializeField] + public string leftAnimationLayerName; + + [SerializeField] + public string leftAnimationStateName; + + [SerializeField] + public string leftAnimationPlaybackRateParam; + + [SerializeField] + public string rightAnimationLayerName; + + [SerializeField] + public string rightAnimationStateName; + + [SerializeField] + public string rightAnimationPlaybackRateParam; + + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + if (isLeft) + { + PlayAnimation(leftAnimationLayerName, leftAnimationStateName, leftAnimationPlaybackRateParam, duration); + } + else + { + PlayAnimation(rightAnimationLayerName, rightAnimationStateName, rightAnimationPlaybackRateParam, duration); + } + if ((bool)muzzleFlashPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + } + if (!NetworkServer.active) + { + return; + } + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.viewer = base.characterBody; + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(base.characterBody.teamComponent.teamIndex); + bullseyeSearch.minDistanceFilter = 0f; + bullseyeSearch.maxDistanceFilter = maxDistance; + bullseyeSearch.searchOrigin = base.inputBank.aimOrigin; + bullseyeSearch.searchDirection = base.inputBank.aimDirection; + bullseyeSearch.maxAngleFilter = 360f; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.filterByDistinctEntity = true; + bullseyeSearch.RefreshCandidates(); + foreach (HurtBox result in bullseyeSearch.GetResults()) + { + GameObject gameObject = result.healthComponent.gameObject; + if (!gameObject) + { + continue; + } + CharacterMotor component = gameObject.GetComponent(); + if ((bool)component) + { + EffectData effectData = new EffectData + { + origin = gameObject.transform.position + }; + GameObject effectPrefab; + if (component.isGrounded) + { + component.ApplyForce(groundedForce, alwaysApply: true, disableAirControlUntilCollision); + effectPrefab = groundedEffectPrefab; + effectData.rotation = Util.QuaternionSafeLookRotation(groundedForce); + } + else + { + component.ApplyForce(airborneForce, alwaysApply: true, disableAirControlUntilCollision); + effectPrefab = airborneEffectPrefab; + effectData.rotation = Util.QuaternionSafeLookRotation(airborneForce); + } + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMissiles.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMissiles.cs new file mode 100644 index 0000000..4cd14b4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMissiles.cs @@ -0,0 +1,140 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class FireMissiles : BaseState +{ + [SerializeField] + public float baseInitialDelay; + + [SerializeField] + public float baseDelayBetweenWaves; + + [SerializeField] + public float baseEndDelay; + + [SerializeField] + public int numWaves; + + [SerializeField] + public int numMissilesPerWave; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public float minSpreadDegrees; + + [SerializeField] + public float rangeSpreadDegrees; + + [SerializeField] + public string fireWaveSoundString; + + [SerializeField] + public bool isSoundScaledByAttackSpeed; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + private float delayBetweenWaves; + + private float duration; + + private int numWavesFired; + + private float timeUntilNextWave; + + private Transform muzzleTransform; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + float num = baseInitialDelay + Mathf.Max(0f, baseDelayBetweenWaves * (float)(numWaves - 1)) + baseEndDelay; + duration = num / attackSpeedStat; + timeUntilNextWave = baseInitialDelay / attackSpeedStat; + delayBetweenWaves = baseDelayBetweenWaves / attackSpeedStat; + muzzleTransform = FindModelChild(muzzleName); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + timeUntilNextWave -= GetDeltaTime(); + while (timeUntilNextWave < 0f && numWavesFired < numWaves) + { + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + timeUntilNextWave += delayBetweenWaves; + numWavesFired++; + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + if (base.isAuthority) + { + Quaternion quaternion = Util.QuaternionSafeLookRotation(GetAimRay().direction); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = muzzleTransform.position; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + for (int i = 0; i < numMissilesPerWave; i++) + { + fireProjectileInfo2.rotation = quaternion * GetRandomRollPitch(); + fireProjectileInfo2.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } + } + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected Quaternion GetRandomRollPitch() + { + Quaternion quaternion = Quaternion.AngleAxis(Random.Range(0, 360), Vector3.forward); + Quaternion quaternion2 = Quaternion.AngleAxis(minSpreadDegrees + Random.Range(0f, rangeSpreadDegrees), Vector3.left); + return quaternion * quaternion2; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMultiBeamFinale.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMultiBeamFinale.cs new file mode 100644 index 0000000..23450f9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMultiBeamFinale.cs @@ -0,0 +1,48 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class FireMultiBeamFinale : BaseFireMultiBeam +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float projectileVerticalSpawnOffset; + + [SerializeField] + public float projectileDamageCoefficient; + + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + protected override void OnFireBeam(Vector3 beamStart, Vector3 beamEnd) + { + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = beamEnd + Vector3.up * projectileVerticalSpawnOffset; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * projectileDamageCoefficient; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + + protected override EntityState InstantiateNextState() + { + return EntityStateCatalog.InstantiateState(ref outer.mainStateType); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMultiBeamSmall.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMultiBeamSmall.cs new file mode 100644 index 0000000..25c5754 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab.Weapon/FireMultiBeamSmall.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace EntityStates.VoidRaidCrab.Weapon; + +public class FireMultiBeamSmall : BaseFireMultiBeam +{ + [SerializeField] + public int numFireBeforeFinale; + + private int fireIndex; + + protected override EntityState InstantiateNextState() + { + if (fireIndex < numFireBeforeFinale - 1) + { + return new FireMultiBeamSmall + { + fireIndex = fireIndex + 1 + }; + } + return new FireMultiBeamFinale(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseSpinBeamAttackState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseSpinBeamAttackState.cs new file mode 100644 index 0000000..94b1c0b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseSpinBeamAttackState.cs @@ -0,0 +1,151 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class BaseSpinBeamAttackState : BaseState +{ + [SerializeField] + public string animLayerName; + + [SerializeField] + public string animStateName; + + [SerializeField] + public string animPlaybackRateParamName; + + [SerializeField] + public float baseDuration; + + public static string headTransformNameInChildLocator; + + public static string muzzleTransformNameInChildLocator; + + public static string headYawParamName; + + [SerializeField] + public AnimationCurve headForwardYCurve; + + private Transform headTransform; + + private Transform muzzleTransform; + + private bool hasHeadSpinOwnership; + + protected float duration { get; private set; } + + protected Animator modelAnimator { get; private set; } + + protected GameObject beamVfxInstance { get; private set; } + + protected float normalizedFixedAge => Mathf.Clamp01(base.fixedAge / duration); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + headTransform = FindModelChild(headTransformNameInChildLocator); + muzzleTransform = FindModelChild(muzzleTransformNameInChildLocator); + duration = baseDuration; + if (!string.IsNullOrEmpty(animLayerName) && !string.IsNullOrEmpty(animStateName)) + { + if (!string.IsNullOrEmpty(animPlaybackRateParamName)) + { + PlayAnimation(animLayerName, animStateName, animPlaybackRateParamName, duration); + } + else + { + PlayAnimation(animLayerName, animStateName); + } + } + if ((bool)modelAnimator) + { + modelAnimator.GetComponent().enabled = true; + } + hasHeadSpinOwnership = true; + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is BaseSpinBeamAttackState baseSpinBeamAttackState) + { + baseSpinBeamAttackState.hasHeadSpinOwnership |= hasHeadSpinOwnership; + hasHeadSpinOwnership = false; + } + } + + public override void OnExit() + { + if (hasHeadSpinOwnership) + { + SetHeadYawRevolutions(0f); + hasHeadSpinOwnership = true; + } + DestroyBeamVFXInstance(); + base.OnExit(); + } + + protected void SetHeadYawRevolutions(float newRevolutions) + { + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(headYawParamName, (0.5f + newRevolutions) % 1f); + } + } + + protected Ray GetBeamRay() + { + _ = muzzleTransform.forward; + Vector3 forward = headTransform.forward; + forward.y = headForwardYCurve.Evaluate(base.fixedAge / duration); + forward.Normalize(); + return new Ray(muzzleTransform.position, forward); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } + + protected void CreateBeamVFXInstance(GameObject beamVfxPrefab) + { + if ((object)beamVfxInstance != null) + { + throw new InvalidOperationException(); + } + beamVfxInstance = UnityEngine.Object.Instantiate(beamVfxPrefab); + beamVfxInstance.transform.SetParent(headTransform, worldPositionStays: true); + UpdateBeamTransforms(); + RoR2Application.onLateUpdate += UpdateBeamTransformsInLateUpdate; + } + + protected void DestroyBeamVFXInstance() + { + if ((object)beamVfxInstance != null) + { + RoR2Application.onLateUpdate -= UpdateBeamTransformsInLateUpdate; + VfxKillBehavior.KillVfxObject(beamVfxInstance); + beamVfxInstance = null; + } + } + + private void UpdateBeamTransformsInLateUpdate() + { + try + { + UpdateBeamTransforms(); + } + catch (Exception exception) + { + Debug.LogException(exception); + } + } + + private void UpdateBeamTransforms() + { + Ray beamRay = GetBeamRay(); + beamVfxInstance.transform.SetPositionAndRotation(beamRay.origin, Quaternion.LookRotation(beamRay.direction)); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseVacuumAttackState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseVacuumAttackState.cs new file mode 100644 index 0000000..be9c8b8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseVacuumAttackState.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public abstract class BaseVacuumAttackState : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public string animLayerName; + + [SerializeField] + public string animStateName; + + [SerializeField] + public string animPlaybackRateParamName; + + public static string vacuumOriginChildLocatorName; + + protected float duration { get; private set; } + + protected Transform vacuumOrigin { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + if (!string.IsNullOrEmpty(animLayerName) && !string.IsNullOrEmpty(animStateName) && !string.IsNullOrEmpty(animPlaybackRateParamName)) + { + PlayAnimation(animLayerName, animStateName, animPlaybackRateParamName, duration); + } + if (!string.IsNullOrEmpty(vacuumOriginChildLocatorName)) + { + vacuumOrigin = FindModelChild(vacuumOriginChildLocatorName); + } + else + { + vacuumOrigin = base.transform; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + OnLifetimeExpiredAuthority(); + } + } + + protected abstract void OnLifetimeExpiredAuthority(); + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseWardWipeState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseWardWipeState.cs new file mode 100644 index 0000000..4a10fe0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/BaseWardWipeState.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class BaseWardWipeState : BaseState +{ + [SerializeField] + public GameObject safeWardDisappearEffectPrefab; + + protected List safeWards = new List(); + + protected FogDamageController fogDamageController; + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (nextState is BaseWardWipeState baseWardWipeState) + { + baseWardWipeState.fogDamageController = fogDamageController; + baseWardWipeState.safeWards = safeWards; + return; + } + if ((bool)fogDamageController) + { + fogDamageController.enabled = false; + } + if (safeWards == null || !NetworkServer.active) + { + return; + } + foreach (GameObject safeWard in safeWards) + { + if ((bool)fogDamageController) + { + IZone component = safeWard.GetComponent(); + fogDamageController.RemoveSafeZone(component); + } + if ((bool)safeWardDisappearEffectPrefab) + { + EffectData effectData = new EffectData(); + effectData.origin = safeWard.transform.position; + EffectManager.SpawnEffect(safeWardDisappearEffectPrefab, effectData, transmit: true); + } + EntityState.Destroy(safeWard); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChannelGauntlet.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChannelGauntlet.cs new file mode 100644 index 0000000..2a34cfb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChannelGauntlet.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RoR2; +using RoR2.HudOverlay; +using UnityEngine; +using UnityEngine.UI; + +namespace EntityStates.VoidRaidCrab; + +public class ChannelGauntlet : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public GameObject overlayPrefab; + + [SerializeField] + public string overlayChildLocatorEntryName; + + [SerializeField] + public string fillImageChildLocatorEntryName; + + private List overlayControllers; + + private HashSet overlayFillImages; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(TeamIndex.Player); + overlayControllers = new List(); + overlayFillImages = new HashSet(); + foreach (TeamComponent item in teamMembers) + { + OverlayController overlayController = HudOverlayManager.AddOverlay(item.gameObject, new OverlayCreationParams + { + prefab = overlayPrefab, + childLocatorEntry = overlayChildLocatorEntryName + }); + overlayController.onInstanceAdded += OnOverlayInstanceAdded; + overlayController.onInstanceRemove += OnOverlayInstanceRemoved; + overlayControllers.Add(overlayController); + } + } + + private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) + { + if (!instance) + { + return; + } + ChildLocator component = instance.GetComponent(); + if ((bool)component) + { + Image image = component.FindChildComponent(fillImageChildLocatorEntryName); + if (image != null) + { + overlayFillImages.Add(image); + } + } + } + + private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) + { + if (!instance) + { + return; + } + ChildLocator component = instance.GetComponent(); + if ((bool)component) + { + Image image = component.FindChildComponent(overlayChildLocatorEntryName); + if (image != null) + { + overlayFillImages.Remove(image); + } + } + } + + public override void OnExit() + { + overlayFillImages.Clear(); + foreach (OverlayController overlayController in overlayControllers) + { + HudOverlayManager.RemoveOverlay(overlayController); + overlayController.onInstanceAdded -= OnOverlayInstanceAdded; + overlayController.onInstanceRemove -= OnOverlayInstanceRemoved; + } + overlayControllers.Clear(); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (duration > 0f) + { + float fillAmount = base.fixedAge / duration; + foreach (Image overlayFillImage in overlayFillImages) + { + overlayFillImage.fillAmount = fillAmount; + } + } + if (base.isAuthority && base.fixedAge >= duration) + { + _ = (bool)VoidRaidGauntletController.instance; + outer.SetNextState(new CloseGauntlet()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeFinalStand.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeFinalStand.cs new file mode 100644 index 0000000..a004a53 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeFinalStand.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class ChargeFinalStand : BaseWardWipeState +{ + [SerializeField] + public float duration; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && (bool)chargeEffectPrefab) + { + Transform transform = modelChildLocator.FindChild(muzzleName) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + fogDamageController = GetComponent(); + fogDamageController.enabled = true; + safeWards = new List(); + PhasedInventorySetter component2 = GetComponent(); + if ((bool)component2 && NetworkServer.active) + { + component2.AdvancePhase(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + FireFinalStand nextState = new FireFinalStand(); + outer.SetNextState(nextState); + } + } + + public override void OnExit() + { + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeGauntlet.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeGauntlet.cs new file mode 100644 index 0000000..45b5a8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeGauntlet.cs @@ -0,0 +1,94 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class ChargeGauntlet : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && (bool)chargeEffectPrefab) + { + Transform transform = modelChildLocator.FindChild(muzzleName) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + PhasedInventorySetter component2 = GetComponent(); + if ((bool)component2 && NetworkServer.active) + { + component2.AdvancePhase(); + } + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + _ = (bool)VoidRaidGauntletController.instance; + outer.SetNextState(new ChannelGauntlet()); + } + } + + public override void OnExit() + { + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeWardWipe.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeWardWipe.cs new file mode 100644 index 0000000..6824af0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ChargeWardWipe.cs @@ -0,0 +1,135 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class ChargeWardWipe : BaseWardWipeState +{ + [SerializeField] + public float duration; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public InteractableSpawnCard safeWardSpawnCard; + + [SerializeField] + public AnimationCurve safeWardSpawnCurve; + + [SerializeField] + public float minDistanceBetweenConsecutiveWards; + + [SerializeField] + public float maxDistanceBetweenConsecutiveWards; + + [SerializeField] + public float maxDistanceToInitialWard; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator && (bool)chargeEffectPrefab) + { + Transform transform = modelChildLocator.FindChild(muzzleName) ?? base.characterBody.coreTransform; + if ((bool)transform) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + fogDamageController = GetComponent(); + fogDamageController.enabled = true; + safeWards = new List(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (bool)safeWardSpawnCard) + { + float time = base.fixedAge / duration; + float f = safeWardSpawnCurve.Evaluate(time); + DirectorPlacementRule directorPlacementRule = null; + while ((float)safeWards.Count < Mathf.Floor(f)) + { + if (directorPlacementRule == null) + { + directorPlacementRule = new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Approximate, + maxDistance = maxDistanceToInitialWard, + minDistance = 0f, + spawnOnTarget = base.gameObject.transform, + preventOverhead = true + }; + } + if (safeWards.Count > 0) + { + directorPlacementRule.maxDistance = maxDistanceBetweenConsecutiveWards; + directorPlacementRule.minDistance = minDistanceBetweenConsecutiveWards; + directorPlacementRule.spawnOnTarget = safeWards[safeWards.Count - 1].transform; + directorPlacementRule.placementMode = DirectorPlacementRule.PlacementMode.Approximate; + } + GameObject gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(safeWardSpawnCard, directorPlacementRule, Run.instance.stageRng)); + if ((bool)gameObject) + { + NetworkServer.Spawn(gameObject); + if ((bool)fogDamageController) + { + IZone component = gameObject.GetComponent(); + fogDamageController.AddSafeZone(component); + } + safeWards.Add(gameObject); + } + else + { + Debug.LogError("Unable to spawn safe ward instance. Are there any ground nodes?"); + } + } + } + if (base.isAuthority && base.fixedAge >= duration) + { + FireWardWipe nextState = new FireWardWipe(); + outer.SetNextState(nextState); + } + } + + public override void OnExit() + { + EntityState.Destroy(chargeEffectInstance); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/CloseGauntlet.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/CloseGauntlet.cs new file mode 100644 index 0000000..f2c8510 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/CloseGauntlet.cs @@ -0,0 +1,43 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class CloseGauntlet : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/Collapse.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/Collapse.cs new file mode 100644 index 0000000..13c0594 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/Collapse.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class Collapse : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new ReEmerge()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/DeathState.cs new file mode 100644 index 0000000..c747032 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/DeathState.cs @@ -0,0 +1,126 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class DeathState : GenericCharacterDeath +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public GameObject initialEffectPrefab; + + [SerializeField] + public string initialEffectMuzzle; + + [SerializeField] + public GameObject explosionEffectPrefab; + + [SerializeField] + public string explosionEffectMuzzle; + + [SerializeField] + public Vector3 ragdollForce; + + [SerializeField] + public float explosionForce; + + [SerializeField] + public bool addPrintController; + + [SerializeField] + public float printDuration; + + [SerializeField] + public float startingPrintBias; + + [SerializeField] + public float maxPrintBias; + + private Transform modelTransform; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration) + { + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateParam, duration, crossfadeDuration); + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)VoidRaidGauntletController.instance) + { + VoidRaidGauntletController.instance.SetCurrentDonutCombatDirectorEnabled(isEnabled: false); + } + modelTransform = GetModelTransform(); + Transform transform = FindModelChild("StandableSurface"); + if ((bool)transform) + { + transform.gameObject.SetActive(value: false); + } + if ((bool)explosionEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(initialEffectPrefab, base.gameObject, initialEffectMuzzle, transmit: false); + } + if (addPrintController) + { + PrintController printController = modelTransform.gameObject.AddComponent(); + printController.printTime = printDuration; + printController.enabled = true; + printController.startingPrintHeight = 99f; + printController.maxPrintHeight = 99f; + printController.startingPrintBias = startingPrintBias; + printController.maxPrintBias = maxPrintBias; + printController.disableWhenFinished = false; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && base.fixedAge >= duration) + { + if ((bool)explosionEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(explosionEffectPrefab, base.gameObject, explosionEffectMuzzle, transmit: true); + } + DestroyBodyAsapServer(); + } + } + + public override void OnExit() + { + if ((bool)modelTransform) + { + RagdollController component = modelTransform.GetComponent(); + Rigidbody component2 = GetComponent(); + if ((bool)component && (bool)component2) + { + component.BeginRagdoll(ragdollForce); + } + ExplodeRigidbodiesOnStart component3 = modelTransform.GetComponent(); + if ((bool)component3) + { + component3.force = explosionForce; + component3.enabled = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/EscapeDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/EscapeDeath.cs new file mode 100644 index 0000000..1080e9f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/EscapeDeath.cs @@ -0,0 +1,119 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class EscapeDeath : GenericCharacterDeath +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public bool addPrintController; + + [SerializeField] + public float printDuration; + + [SerializeField] + public float startingPrintHeight; + + [SerializeField] + public float maxPrintHeight; + + [SerializeField] + public string gauntletEntranceChildName; + + [SerializeField] + public string enterSoundString; + + private Vector3 gauntletEntrancePosition; + + private Transform gauntletEntranceTransform; + + private NetworkInstanceId netId; + + protected override bool shouldAutoDestroy => false; + + protected override void PlayDeathAnimation(float crossfadeDuration) + { + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackRateParam, duration, crossfadeDuration); + } + + public override void OnEnter() + { + base.OnEnter(); + netId = NetworkInstanceId.Invalid; + if ((bool)base.characterBody && (bool)base.characterBody.master) + { + netId = base.characterBody.master.netId; + } + Util.PlaySound(enterSoundString, base.gameObject); + if (addPrintController) + { + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + PrintController printController = modelTransform.gameObject.AddComponent(); + printController.printTime = printDuration; + printController.enabled = true; + printController.startingPrintHeight = startingPrintHeight; + printController.maxPrintHeight = maxPrintHeight; + printController.startingPrintBias = 0f; + printController.maxPrintBias = 0f; + printController.disableWhenFinished = false; + printController.printCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + } + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + gauntletEntranceTransform = modelChildLocator.FindChild(gauntletEntranceChildName); + RefreshGauntletEntrancePosition(); + } + } + + public override void OnExit() + { + if (NetworkServer.active) + { + RefreshGauntletEntrancePosition(); + VoidRaidGauntletController.instance.TryOpenGauntlet(gauntletEntrancePosition, netId); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active) + { + RefreshGauntletEntrancePosition(); + } + if (base.isAuthority && base.fixedAge >= duration) + { + EntityState.Destroy(base.gameObject); + } + } + + private void RefreshGauntletEntrancePosition() + { + if ((bool)gauntletEntranceTransform) + { + gauntletEntrancePosition = gauntletEntranceTransform.position; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/FireFinalStand.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/FireFinalStand.cs new file mode 100644 index 0000000..443d109 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/FireFinalStand.cs @@ -0,0 +1,72 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class FireFinalStand : BaseWardWipeState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public BuffDef requiredBuffToKill; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)muzzleFlashPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + } + if (!fogDamageController) + { + return; + } + if (NetworkServer.active) + { + foreach (CharacterBody affectedBody in fogDamageController.GetAffectedBodies()) + { + if (!requiredBuffToKill || affectedBody.HasBuff(requiredBuffToKill)) + { + affectedBody.healthComponent.Suicide(base.gameObject, base.gameObject, DamageType.VoidDeath); + } + } + } + fogDamageController.enabled = false; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/FireWardWipe.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/FireWardWipe.cs new file mode 100644 index 0000000..3dd6182 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/FireWardWipe.cs @@ -0,0 +1,87 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class FireWardWipe : BaseWardWipeState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + [SerializeField] + public BuffDef requiredBuffToKill; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)muzzleFlashPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + } + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + if (!fogDamageController) + { + return; + } + if (NetworkServer.active) + { + foreach (CharacterBody affectedBody in fogDamageController.GetAffectedBodies()) + { + if (!requiredBuffToKill || affectedBody.HasBuff(requiredBuffToKill)) + { + affectedBody.healthComponent.Suicide(base.gameObject, base.gameObject, DamageType.VoidDeath); + } + } + } + fogDamageController.enabled = false; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Pain; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/LegBreakStunState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/LegBreakStunState.cs new file mode 100644 index 0000000..6549360 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/LegBreakStunState.cs @@ -0,0 +1,35 @@ +namespace EntityStates.VoidRaidCrab; + +public class LegBreakStunState : BaseState +{ + public static string animLayerName; + + public static string animStateName; + + public static string animPlaybackRateParamName; + + public static float baseDuration; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + PlayAnimation(animLayerName, animStateName, animPlaybackRateParamName, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ReEmerge.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ReEmerge.cs new file mode 100644 index 0000000..8f874a3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/ReEmerge.cs @@ -0,0 +1,48 @@ +using RoR2.VoidRaidCrab; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class ReEmerge : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + if (NetworkServer.active) + { + CentralLegController component = GetComponent(); + if ((bool)component) + { + component.RegenerateAllBrokenServer(); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpawnState.cs new file mode 100644 index 0000000..008e77f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpawnState.cs @@ -0,0 +1,118 @@ +using RoR2; +using RoR2.VoidRaidCrab; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class SpawnState : BaseState +{ + [SerializeField] + public float duration = 4f; + + [SerializeField] + public string spawnSoundString; + + [SerializeField] + public GameObject spawnEffectPrefab; + + [SerializeField] + public string spawnMuzzleName; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public bool doLegs; + + [SerializeField] + public CharacterSpawnCard jointSpawnCard; + + [SerializeField] + public string leg1Name; + + [SerializeField] + public string leg2Name; + + [SerializeField] + public string leg3Name; + + [SerializeField] + public string leg4Name; + + [SerializeField] + public string leg5Name; + + [SerializeField] + public string leg6Name; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + if ((bool)spawnEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(spawnEffectPrefab, base.gameObject, spawnMuzzleName, transmit: false); + } + if (doLegs && NetworkServer.active) + { + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)jointSpawnCard && (bool)modelChildLocator) + { + DirectorPlacementRule placementRule = new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Direct, + spawnOnTarget = base.transform + }; + SpawnJointBodyForLegServer(leg1Name, modelChildLocator, placementRule); + SpawnJointBodyForLegServer(leg2Name, modelChildLocator, placementRule); + SpawnJointBodyForLegServer(leg3Name, modelChildLocator, placementRule); + SpawnJointBodyForLegServer(leg4Name, modelChildLocator, placementRule); + SpawnJointBodyForLegServer(leg5Name, modelChildLocator, placementRule); + SpawnJointBodyForLegServer(leg6Name, modelChildLocator, placementRule); + } + } + } + + private void SpawnJointBodyForLegServer(string legName, ChildLocator childLocator, DirectorPlacementRule placementRule) + { + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(jointSpawnCard, placementRule, Run.instance.stageRng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + GameObject gameObject = DirectorCore.instance?.TrySpawnObject(directorSpawnRequest); + Transform transform = childLocator.FindChild(legName); + if (!gameObject || !transform) + { + return; + } + CharacterMaster component = gameObject.GetComponent(); + if ((bool)component) + { + LegController component2 = transform.GetComponent(); + if ((bool)component2) + { + component2.SetJointMaster(component, transform.GetComponent()); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamAttack.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamAttack.cs new file mode 100644 index 0000000..813e3f9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamAttack.cs @@ -0,0 +1,95 @@ +using RoR2; +using RoR2.Audio; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class SpinBeamAttack : BaseSpinBeamAttackState +{ + public static AnimationCurve revolutionsCurve; + + public static GameObject beamVfxPrefab; + + public static float beamRadius = 16f; + + public static float beamMaxDistance = 400f; + + public static float beamDpsCoefficient = 1f; + + public static float beamTickFrequency = 4f; + + public static GameObject beamImpactEffectPrefab; + + public static LoopSoundDef loopSound; + + public static string enterSoundString; + + private float beamTickTimer; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + public override void OnEnter() + { + base.OnEnter(); + CreateBeamVFXInstance(beamVfxPrefab); + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSound); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void OnExit() + { + LoopSoundManager.StopSoundLoopLocal(loopPtr); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= base.duration && base.isAuthority) + { + outer.SetNextState(new SpinBeamWindDown()); + } + if (base.isAuthority) + { + if (beamTickTimer <= 0f) + { + beamTickTimer += 1f / beamTickFrequency; + FireBeamBulletAuthority(); + } + beamTickTimer -= GetDeltaTime(); + } + SetHeadYawRevolutions(revolutionsCurve.Evaluate(base.normalizedFixedAge)); + } + + private void FireBeamBulletAuthority() + { + Ray beamRay = GetBeamRay(); + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.muzzleName = BaseSpinBeamAttackState.muzzleTransformNameInChildLocator; + bulletAttack.origin = beamRay.origin; + bulletAttack.aimVector = beamRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = 0f; + bulletAttack.maxDistance = 400f; + bulletAttack.hitMask = LayerIndex.CommonMasks.bullet; + bulletAttack.stopperMask = 0; + bulletAttack.bulletCount = 1u; + bulletAttack.radius = beamRadius; + bulletAttack.smartCollision = false; + bulletAttack.queryTriggerInteraction = QueryTriggerInteraction.Ignore; + bulletAttack.procCoefficient = 1f; + bulletAttack.procChainMask = default(ProcChainMask); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.damage = beamDpsCoefficient * damageStat / beamTickFrequency; + bulletAttack.damageColorIndex = DamageColorIndex.Default; + bulletAttack.damageType = DamageType.Generic; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.force = 0f; + bulletAttack.hitEffectPrefab = beamImpactEffectPrefab; + bulletAttack.tracerEffectPrefab = null; + bulletAttack.isCrit = false; + bulletAttack.HitEffectNormal = false; + bulletAttack.Fire(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamEnter.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamEnter.cs new file mode 100644 index 0000000..3280018 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamEnter.cs @@ -0,0 +1,13 @@ +namespace EntityStates.VoidRaidCrab; + +public class SpinBeamEnter : BaseSpinBeamAttackState +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= base.duration && base.isAuthority) + { + outer.SetNextState(new SpinBeamWindUp()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamExit.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamExit.cs new file mode 100644 index 0000000..de20f9c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamExit.cs @@ -0,0 +1,36 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class SpinBeamExit : BaseSpinBeamAttackState +{ + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= base.duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamWindDown.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamWindDown.cs new file mode 100644 index 0000000..f4b59cd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamWindDown.cs @@ -0,0 +1,27 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class SpinBeamWindDown : BaseSpinBeamAttackState +{ + public static AnimationCurve revolutionsCurve; + + public static string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= base.duration && base.isAuthority) + { + outer.SetNextState(new SpinBeamExit()); + } + SetHeadYawRevolutions(revolutionsCurve.Evaluate(base.normalizedFixedAge)); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamWindUp.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamWindUp.cs new file mode 100644 index 0000000..6291dd3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/SpinBeamWindUp.cs @@ -0,0 +1,30 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class SpinBeamWindUp : BaseSpinBeamAttackState +{ + public static AnimationCurve revolutionsCurve; + + public static GameObject warningLaserPrefab; + + public static string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + CreateBeamVFXInstance(warningLaserPrefab); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= base.duration && base.isAuthority) + { + outer.SetNextState(new SpinBeamAttack()); + } + SetHeadYawRevolutions(revolutionsCurve.Evaluate(base.normalizedFixedAge)); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/TurnState.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/TurnState.cs new file mode 100644 index 0000000..23eb368 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/TurnState.cs @@ -0,0 +1,141 @@ +using RoR2.VoidRaidCrab; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class TurnState : GenericCharacterMain +{ + [SerializeField] + public float duration = 1f; + + [SerializeField] + public float turnDegrees = 22.5f; + + [SerializeField] + public int maxNumConsecutiveTurns; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string clockwiseAnimationStateName; + + [SerializeField] + public string counterClockwiseAnimationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private CentralLegController centralLegController; + + private CentralLegController.SuppressBreaksRequest suppressBreaksRequest; + + private int turnCount = 1; + + private bool isClockwiseTurn; + + private bool canTurn; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority) + { + centralLegController = GetComponent(); + if ((bool)centralLegController) + { + suppressBreaksRequest = centralLegController.SuppressBreaks(); + } + float dirToAimDegrees = GetDirToAimDegrees(); + if (dirToAimDegrees >= turnDegrees) + { + isClockwiseTurn = true; + canTurn = true; + } + else if (dirToAimDegrees <= 0f - turnDegrees) + { + isClockwiseTurn = false; + canTurn = true; + } + } + if (canTurn) + { + if (isClockwiseTurn) + { + PlayAnimation(animationLayerName, clockwiseAnimationStateName, animationPlaybackRateParam, duration); + } + else + { + PlayAnimation(animationLayerName, counterClockwiseAnimationStateName, animationPlaybackRateParam, duration); + } + } + else if (base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + suppressBreaksRequest?.Dispose(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + if (Mathf.Abs(GetDirToAimDegrees()) >= turnDegrees && (bool)centralLegController && !centralLegController.AreAnyBreaksPending() && turnCount < maxNumConsecutiveTurns) + { + TurnState turnState = new TurnState(); + turnState.turnCount = turnCount + 1; + outer.SetNextState(turnState); + } + else + { + outer.SetNextStateToMain(); + } + } + } + + public float GetDirToAimDegrees() + { + float num = 0f; + if ((bool)base.inputBank && (bool)base.characterDirection) + { + Vector3 rhs = base.inputBank.aimDirection; + rhs.y = 0f; + rhs.Normalize(); + Vector3 forward = base.characterDirection.forward; + forward.y = 0f; + forward.Normalize(); + num = Mathf.Acos(Vector3.Dot(forward, rhs)) * 57.29578f; + if (Vector3.Dot(Vector3.Cross(forward, rhs), Vector3.up) < 0f) + { + num *= -1f; + } + } + return num; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(isClockwiseTurn); + writer.Write(canTurn); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + isClockwiseTurn = reader.ReadBoolean(); + canTurn = reader.ReadBoolean(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumAttack.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumAttack.cs new file mode 100644 index 0000000..4adb82b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumAttack.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using HG; +using RoR2; +using RoR2.Audio; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidRaidCrab; + +public class VacuumAttack : BaseVacuumAttackState +{ + public static AnimationCurve killRadiusCurve; + + public static AnimationCurve pullMagnitudeCurve; + + public static float losObstructionFactor = 0.5f; + + public static GameObject killSphereVfxPrefab; + + public static GameObject environmentVfxPrefab; + + public static LoopSoundDef loopSound; + + private CharacterLosTracker losTracker; + + private VFXHelper killSphereVfxHelper; + + private VFXHelper environmentVfxHelper; + + private SphereSearch killSearch; + + private float killRadius = 1f; + + private BodyIndex jointBodyIndex = BodyIndex.None; + + private LoopSoundManager.SoundLoopPtr loopPtr; + + public override void OnEnter() + { + base.OnEnter(); + losTracker = new CharacterLosTracker(); + losTracker.enabled = true; + killSphereVfxHelper = VFXHelper.Rent(); + killSphereVfxHelper.vfxPrefabReference = killSphereVfxPrefab; + killSphereVfxHelper.followedTransform = base.vacuumOrigin; + killSphereVfxHelper.useFollowedTransformScale = false; + killSphereVfxHelper.enabled = true; + UpdateKillSphereVfx(); + environmentVfxHelper = VFXHelper.Rent(); + environmentVfxHelper.vfxPrefabReference = environmentVfxPrefab; + environmentVfxHelper.followedTransform = base.vacuumOrigin; + environmentVfxHelper.useFollowedTransformScale = false; + environmentVfxHelper.enabled = true; + loopPtr = LoopSoundManager.PlaySoundLoopLocal(base.gameObject, loopSound); + if (NetworkServer.active) + { + killSearch = new SphereSearch(); + } + jointBodyIndex = BodyCatalog.FindBodyIndex("VoidRaidCrabJointBody"); + } + + public override void OnExit() + { + killSphereVfxHelper = VFXHelper.Return(killSphereVfxHelper); + environmentVfxHelper = VFXHelper.Return(environmentVfxHelper); + losTracker.enabled = false; + losTracker.Dispose(); + losTracker = null; + LoopSoundManager.StopSoundLoopLocal(loopPtr); + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + float time = Mathf.Clamp01(base.fixedAge / base.duration); + killRadius = killRadiusCurve.Evaluate(time); + UpdateKillSphereVfx(); + Vector3 position = base.vacuumOrigin.position; + losTracker.origin = position; + losTracker.Step(); + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + float num = pullMagnitudeCurve.Evaluate(time); + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + CharacterBody characterBody = readOnlyInstancesList[i]; + if ((object)characterBody == base.characterBody) + { + continue; + } + bool flag = losTracker.CheckBodyHasLos(characterBody); + if (characterBody.hasEffectiveAuthority) + { + IDisplacementReceiver component = characterBody.GetComponent(); + if (component != null) + { + float num2 = (flag ? 1f : losObstructionFactor); + component.AddDisplacement((position - characterBody.transform.position).normalized * (num * num2 * GetDeltaTime())); + } + } + } + if (!NetworkServer.active) + { + return; + } + List list = CollectionPool>.RentCollection(); + List list2 = CollectionPool>.RentCollection(); + try + { + killSearch.radius = killRadius; + killSearch.origin = position; + killSearch.mask = LayerIndex.entityPrecise.mask; + killSearch.RefreshCandidates(); + killSearch.OrderCandidatesByDistance(); + killSearch.FilterCandidatesByDistinctHurtBoxEntities(); + killSearch.GetHurtBoxes(list); + for (int j = 0; j < list.Count; j++) + { + HurtBox hurtBox = list[j]; + if ((bool)hurtBox.healthComponent) + { + list2.Add(hurtBox.healthComponent); + } + } + for (int k = 0; k < list2.Count; k++) + { + HealthComponent healthComponent = list2[k]; + if ((object)base.healthComponent != healthComponent && healthComponent.body.bodyIndex != jointBodyIndex) + { + healthComponent.Suicide(base.gameObject, base.gameObject, DamageType.VoidDeath); + } + } + } + finally + { + list2 = CollectionPool>.ReturnCollection(list2); + list = CollectionPool>.ReturnCollection(list); + } + } + + private void UpdateKillSphereVfx() + { + if ((bool)killSphereVfxHelper.vfxInstanceTransform) + { + killSphereVfxHelper.vfxInstanceTransform.localScale = Vector3.one * killRadius; + } + } + + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new VacuumWindDown()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumEnter.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumEnter.cs new file mode 100644 index 0000000..caf4cfa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumEnter.cs @@ -0,0 +1,9 @@ +namespace EntityStates.VoidRaidCrab; + +public class VacuumEnter : BaseVacuumAttackState +{ + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new VacuumWindUp()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumExit.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumExit.cs new file mode 100644 index 0000000..972e188 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumExit.cs @@ -0,0 +1,32 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.VoidRaidCrab; + +public class VacuumExit : BaseVacuumAttackState +{ + [SerializeField] + public SkillDef skillDefToReplaceAtStocksEmpty; + + [SerializeField] + public SkillDef nextSkillDef; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)nextSkillDef) + { + GenericSkill genericSkill = base.skillLocator.FindSkillByDef(skillDefToReplaceAtStocksEmpty); + if ((bool)genericSkill && genericSkill.stock == 0) + { + genericSkill.SetBaseSkill(nextSkillDef); + } + } + } + + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumWindDown.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumWindDown.cs new file mode 100644 index 0000000..b3b5de6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumWindDown.cs @@ -0,0 +1,9 @@ +namespace EntityStates.VoidRaidCrab; + +public class VacuumWindDown : BaseVacuumAttackState +{ + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new VacuumExit()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumWindUp.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumWindUp.cs new file mode 100644 index 0000000..53a9c5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/VacuumWindUp.cs @@ -0,0 +1,9 @@ +namespace EntityStates.VoidRaidCrab; + +public class VacuumWindUp : BaseVacuumAttackState +{ + protected override void OnLifetimeExpiredAuthority() + { + outer.SetNextState(new VacuumAttack()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/WaitForLegsAvailable.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/WaitForLegsAvailable.cs new file mode 100644 index 0000000..df0bcd8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidRaidCrab/WaitForLegsAvailable.cs @@ -0,0 +1,30 @@ +using RoR2.VoidRaidCrab; + +namespace EntityStates.VoidRaidCrab; + +public class WaitForLegsAvailable : BaseState +{ + public EntityState nextState; + + private CentralLegController centralLegController; + + public override void OnEnter() + { + base.OnEnter(); + centralLegController = GetComponent(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && !centralLegController.AreLegsBlockingBodyAnimation()) + { + outer.SetNextState(nextState); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return nextState.GetMinimumInterruptPriority(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/CorruptMode.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/CorruptMode.cs new file mode 100644 index 0000000..8c33455 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/CorruptMode.cs @@ -0,0 +1,62 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.CorruptMode; + +public class CorruptMode : CorruptModeBase +{ + [SerializeField] + public SkillDef primaryOverrideSkillDef; + + [SerializeField] + public SkillDef secondaryOverrideSkillDef; + + [SerializeField] + public SkillDef utilityOverrideSkillDef; + + [SerializeField] + public SkillDef specialOverrideSkillDef; + + public override void OnEnter() + { + base.OnEnter(); + if (base.isAuthority && (bool)base.skillLocator) + { + base.skillLocator.primary.SetSkillOverride(this, primaryOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + base.skillLocator.secondary.SetSkillOverride(this, secondaryOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + base.skillLocator.utility.SetSkillOverride(this, utilityOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + base.skillLocator.special.SetSkillOverride(this, specialOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + } + if ((bool)voidSurvivorController && NetworkServer.active) + { + base.characterBody.AddBuff(voidSurvivorController.corruptedBuffDef); + } + } + + public override void OnExit() + { + if (base.isAuthority && (bool)base.skillLocator) + { + base.skillLocator.primary.UnsetSkillOverride(this, primaryOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + base.skillLocator.secondary.UnsetSkillOverride(this, secondaryOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + base.skillLocator.utility.UnsetSkillOverride(this, utilityOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + base.skillLocator.special.UnsetSkillOverride(this, specialOverrideSkillDef, GenericSkill.SkillOverridePriority.Upgrade); + } + if ((bool)voidSurvivorController && NetworkServer.active) + { + base.characterBody.RemoveBuff(voidSurvivorController.corruptedBuffDef); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)voidSurvivorController && voidSurvivorController.corruption <= voidSurvivorController.minimumCorruption && !voidSurvivorController.isPermanentlyCorrupted && (bool)voidSurvivorController.bodyStateMachine) + { + voidSurvivorController.bodyStateMachine.SetInterruptState(new ExitCorruptionTransition(), InterruptPriority.Skill); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/CorruptModeBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/CorruptModeBase.cs new file mode 100644 index 0000000..c08241e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/CorruptModeBase.cs @@ -0,0 +1,14 @@ +using RoR2; + +namespace EntityStates.VoidSurvivor.CorruptMode; + +public class CorruptModeBase : BaseState +{ + protected VoidSurvivorController voidSurvivorController; + + public override void OnEnter() + { + base.OnEnter(); + voidSurvivorController = GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/UncorruptedMode.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/UncorruptedMode.cs new file mode 100644 index 0000000..dd9c6e4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.CorruptMode/UncorruptedMode.cs @@ -0,0 +1,13 @@ +namespace EntityStates.VoidSurvivor.CorruptMode; + +public class UncorruptedMode : CorruptModeBase +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && (bool)voidSurvivorController && voidSurvivorController.corruption >= voidSurvivorController.maxCorruption && (bool)voidSurvivorController.bodyStateMachine) + { + voidSurvivorController.bodyStateMachine.SetInterruptState(new EnterCorruptionTransition(), InterruptPriority.Skill); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Vent/VentCorruption.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Vent/VentCorruption.cs new file mode 100644 index 0000000..fb0205b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Vent/VentCorruption.cs @@ -0,0 +1,161 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Vent; + +public class VentCorruption : GenericCharacterMain +{ + [SerializeField] + public float minimumDuration; + + [SerializeField] + public float maximumDuration; + + [SerializeField] + public string leftVentEffectChildLocatorEntry; + + [SerializeField] + public string rightVentEffectChildLocatorEntry; + + [SerializeField] + public string miniVentEffectChildLocatorEntry; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string exitSoundString; + + [SerializeField] + public float animationCrossfadeDuration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string enterAnimationStateName; + + [SerializeField] + public string exitAnimationStateName; + + [SerializeField] + public float hoverVelocity; + + [SerializeField] + public float hoverAcceleration; + + [SerializeField] + public float healingPercentagePerSecond; + + [SerializeField] + public float healingTickRate; + + [SerializeField] + public float corruptionReductionPerSecond; + + [SerializeField] + public GameObject crosshairOverridePrefab; + + [SerializeField] + public float turnSpeed; + + private float healPerTick; + + private float healTickStopwatch; + + private float corruptionReductionPerTick; + + private Vector3 liftVector = Vector3.up; + + private VoidSurvivorController voidSurvivorController; + + private CrosshairUtils.OverrideRequest crosshairOverrideRequest; + + private float previousTurnSpeed; + + public override void OnEnter() + { + base.OnEnter(); + voidSurvivorController = GetComponent(); + voidSurvivorController = GetComponent(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayCrossfade(animationLayerName, enterAnimationStateName, animationCrossfadeDuration); + healPerTick = base.healthComponent.fullHealth * healingPercentagePerSecond / healingTickRate; + corruptionReductionPerTick = corruptionReductionPerSecond / healingTickRate; + FindModelChild(leftVentEffectChildLocatorEntry)?.gameObject.SetActive(value: true); + FindModelChild(rightVentEffectChildLocatorEntry)?.gameObject.SetActive(value: true); + FindModelChild(miniVentEffectChildLocatorEntry)?.gameObject.SetActive(value: true); + if ((bool)crosshairOverridePrefab) + { + crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); + } + if ((bool)base.characterDirection) + { + previousTurnSpeed = base.characterDirection.turnSpeed; + base.characterDirection.turnSpeed = turnSpeed; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(1f); + if (NetworkServer.active) + { + healTickStopwatch += GetDeltaTime(); + if (healTickStopwatch > 1f / healingTickRate) + { + healTickStopwatch -= 1f / healingTickRate; + base.healthComponent.Heal(healPerTick, default(ProcChainMask)); + if ((bool)voidSurvivorController) + { + voidSurvivorController.AddCorruption(0f - corruptionReductionPerTick); + } + } + } + if (!base.isAuthority) + { + return; + } + if ((bool)base.characterMotor) + { + float y = base.characterMotor.velocity.y; + if (y < hoverVelocity) + { + y = Mathf.MoveTowards(y, hoverVelocity, hoverAcceleration * GetDeltaTime()); + base.characterMotor.velocity = new Vector3(base.characterMotor.velocity.x, y, base.characterMotor.velocity.z); + } + } + if (base.fixedAge >= maximumDuration || (base.fixedAge >= minimumDuration && (bool)voidSurvivorController && voidSurvivorController.corruption <= voidSurvivorController.minimumCorruption)) + { + outer.SetNextStateToMain(); + } + } + + protected override bool CanExecuteSkill(GenericSkill skillSlot) + { + return false; + } + + public override void OnExit() + { + if ((bool)base.characterDirection) + { + base.characterDirection.turnSpeed = previousTurnSpeed; + } + crosshairOverrideRequest?.Dispose(); + FindModelChild(leftVentEffectChildLocatorEntry)?.gameObject.SetActive(value: false); + FindModelChild(rightVentEffectChildLocatorEntry)?.gameObject.SetActive(value: false); + FindModelChild(miniVentEffectChildLocatorEntry)?.gameObject.SetActive(value: false); + PlayCrossfade(animationLayerName, exitAnimationStateName, animationCrossfadeDuration); + Util.PlaySound(exitSoundString, base.gameObject); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCorruptHandBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCorruptHandBeam.cs new file mode 100644 index 0000000..1316930 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCorruptHandBeam.cs @@ -0,0 +1,61 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeCorruptHandBeam : BaseSkillState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + GetAimRay(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + base.characterBody.SetAimTimer(3f); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new FireCorruptHandBeam + { + activatorSkillSlot = base.activatorSkillSlot + }); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrabCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrabCannon.cs new file mode 100644 index 0000000..957c6cc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrabCannon.cs @@ -0,0 +1,137 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeCrabCannon : BaseSkillState +{ + [SerializeField] + public float baseDurationPerGrenade; + + [SerializeField] + public float minimumDuration; + + [SerializeField] + public string muzzle; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string chargeStockSoundString; + + [SerializeField] + public string chargeLoopStartSoundString; + + [SerializeField] + public string chargeLoopStopSoundString; + + [SerializeField] + public float bloomPerGrenade; + + [SerializeField] + public float corruptionPerGrenade; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + private VoidSurvivorController voidSurvivorController; + + private GameObject chargeEffectInstance; + + private int grenadeCount; + + private int lastGrenadeCount; + + private float durationPerGrenade; + + private float nextGrenadeStopwatch; + + private static int BufferEmptyStateHash = Animator.StringToHash("BufferEmpty"); + + public override void OnEnter() + { + base.OnEnter(); + voidSurvivorController = GetComponent(); + PlayAnimation(animationLayerName, animationStateName); + durationPerGrenade = baseDurationPerGrenade / attackSpeedStat; + Util.PlaySound(chargeLoopStartSoundString, base.gameObject); + AddGrenade(); + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if (!component) + { + return; + } + Transform transform = component.FindChild(muzzle); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffectInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = durationPerGrenade; + } + } + } + + public override void OnExit() + { + base.OnExit(); + Util.PlaySound(chargeLoopStopSoundString, base.gameObject); + PlayAnimation(animationLayerName, BufferEmptyStateHash); + EntityState.Destroy(chargeEffectInstance); + } + + private void AddGrenade() + { + grenadeCount++; + if ((bool)voidSurvivorController && NetworkServer.active) + { + voidSurvivorController.AddCorruption(corruptionPerGrenade); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(3f); + nextGrenadeStopwatch += GetDeltaTime(); + if (nextGrenadeStopwatch > durationPerGrenade && base.activatorSkillSlot.stock > 0) + { + AddGrenade(); + nextGrenadeStopwatch -= durationPerGrenade; + base.activatorSkillSlot.DeductStock(1); + } + float value = bloomPerGrenade * (float)lastGrenadeCount; + base.characterBody.SetSpreadBloom(value); + if (lastGrenadeCount < grenadeCount) + { + Util.PlaySound(chargeStockSoundString, base.gameObject); + } + if (!IsKeyDownAuthority() && base.fixedAge > minimumDuration / attackSpeedStat && base.isAuthority) + { + FireCrabCannon fireCrabCannon = new FireCrabCannon(); + fireCrabCannon.grenadeCountMax = grenadeCount; + outer.SetNextState(fireCrabCannon); + } + else + { + lastGrenadeCount = grenadeCount; + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushBase.cs new file mode 100644 index 0000000..89c08f5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushBase.cs @@ -0,0 +1,74 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeCrushBase : BaseSkillState +{ + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string chargeSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + protected float duration; + + private uint soundID; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + soundID = Util.PlayAttackSpeedSound(chargeSoundString, base.gameObject, attackSpeedStat); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackParameterName, duration); + base.characterBody.SetAimTimer(duration + 1f); + Transform transform = FindModelChild(muzzle); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + ObjectScaleCurve component2 = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + if ((bool)component2) + { + component2.timeMax = duration; + } + } + } + + public override void OnExit() + { + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + AkSoundEngine.StopPlayingID(soundID); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushCorruption.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushCorruption.cs new file mode 100644 index 0000000..2a35a27 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushCorruption.cs @@ -0,0 +1,13 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeCrushCorruption : ChargeCrushBase +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new CrushCorruption()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushHealth.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushHealth.cs new file mode 100644 index 0000000..e074223 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeCrushHealth.cs @@ -0,0 +1,13 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeCrushHealth : ChargeCrushBase +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new CrushHealth()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeHandBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeHandBeam.cs new file mode 100644 index 0000000..fdfc889 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeHandBeam.cs @@ -0,0 +1,58 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeHandBeam : BaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + GetAimRay(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + base.characterBody.SetAimTimer(3f); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge > duration) + { + outer.SetNextState(new FireHandBeam()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeMegaBlaster.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeMegaBlaster.cs new file mode 100644 index 0000000..0b5e70d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ChargeMegaBlaster.cs @@ -0,0 +1,93 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class ChargeMegaBlaster : BaseSkillState +{ + [SerializeField] + public float minimumDuration = 0.1f; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string chargeSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + private float duration; + + private uint soundID; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + soundID = Util.PlayAttackSpeedSound(chargeSoundString, base.gameObject, attackSpeedStat); + PlayAnimation(animationLayerName, animationStateName); + base.characterBody.SetAimTimer(duration + 1f); + Transform transform = FindModelChild(muzzle); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + ObjectScaleCurve component2 = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + if ((bool)component2) + { + component2.timeMax = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + if (base.fixedAge >= duration) + { + outer.SetNextState(new ReadyMegaBlaster + { + activatorSkillSlot = base.activatorSkillSlot + }); + } + else if (!IsKeyDownAuthority() && base.fixedAge > minimumDuration) + { + outer.SetNextState(new FireMegaBlasterSmall()); + } + } + } + + public override void OnExit() + { + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + AkSoundEngine.StopPlayingID(soundID); + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushBase.cs new file mode 100644 index 0000000..9963f14 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushBase.cs @@ -0,0 +1,102 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class CrushBase : BaseState +{ + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public float selfHealFraction; + + [SerializeField] + public float corruptionChange; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + GetAimRay(); + duration = baseDuration / attackSpeedStat; + StartAimMode(duration + 2f); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(enterSoundString, base.gameObject); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (NetworkServer.active) + { + ProcChainMask procChainMask = default(ProcChainMask); + procChainMask.AddProc(ProcType.VoidSurvivorCrush); + if (selfHealFraction > 0f) + { + base.healthComponent.HealFraction(selfHealFraction, procChainMask); + } + else + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = (0f - base.healthComponent.fullCombinedHealth) * selfHealFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal | DamageType.BypassArmor; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = procChainMask; + base.healthComponent.TakeDamage(damageInfo); + } + VoidSurvivorController component = GetComponent(); + if ((bool)component) + { + component.AddCorruption(corruptionChange); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushCorruption.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushCorruption.cs new file mode 100644 index 0000000..a3f881f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushCorruption.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class CrushCorruption : CrushBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushHealth.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushHealth.cs new file mode 100644 index 0000000..66aa7e4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/CrushHealth.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class CrushHealth : CrushBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/EnterSwingMelee.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/EnterSwingMelee.cs new file mode 100644 index 0000000..545dc4a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/EnterSwingMelee.cs @@ -0,0 +1,46 @@ +using RoR2.Skills; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class EnterSwingMelee : BaseState, SteppedSkillDef.IStepSetter +{ + public int step; + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + step = i; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)step); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + step = reader.ReadByte(); + } + + public override void OnEnter() + { + base.OnEnter(); + switch (step) + { + case 0: + outer.SetNextState(new SwingMelee1()); + break; + case 1: + outer.SetNextState(new SwingMelee2()); + break; + case 2: + outer.SetNextState(new SwingMelee3()); + break; + default: + outer.SetNextState(new SwingMelee1()); + break; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster1.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster1.cs new file mode 100644 index 0000000..0e92732 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster1.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireBlaster1 : FireBlasterBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster2.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster2.cs new file mode 100644 index 0000000..5fb0ba5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster2.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireBlaster2 : FireBlasterBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster3.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster3.cs new file mode 100644 index 0000000..2c0b1d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster3.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireBlaster3 : FireBlasterBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster4.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster4.cs new file mode 100644 index 0000000..5cf629c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlaster4.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireBlaster4 : FireBlasterBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlasterBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlasterBase.cs new file mode 100644 index 0000000..e1434a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireBlasterBase.cs @@ -0,0 +1,153 @@ +using RoR2; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireBlasterBase : BaseSkillState, SteppedSkillDef.IStepSetter +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float attackSoundPitchPerStep; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public string muzzle; + + [SerializeField] + public float spread; + + [SerializeField] + public int projectileCount; + + [SerializeField] + public float yawPerProjectile; + + [SerializeField] + public float offsetPerProjectile; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public int burstCount; + + [SerializeField] + public bool canCharge; + + private float duration; + + private float interruptDuration; + + public int step; + + void SteppedSkillDef.IStepSetter.SetStep(int i) + { + step = i; + } + + public override void OnEnter() + { + base.OnEnter(); + base.activatorSkillSlot = base.skillLocator.primary; + GetAimRay(); + duration = baseDuration / attackSpeedStat; + StartAimMode(duration + 2f); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, 1f + (float)step * attackSoundPitchPerStep); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + FireProjectiles(); + } + } + + private void FireProjectiles() + { + for (int i = 0; i < projectileCount; i++) + { + float num = (float)i - (float)(projectileCount - 1) / 2f; + float bonusYaw = num * yawPerProjectile; + float num2 = num * offsetPerProjectile; + Ray aimRay = GetAimRay(); + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, base.characterBody.spreadBloomAngle + spread, 1f, 1f, bonusYaw); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = aimRay.origin + Vector3.Cross(aimRay.direction, Vector3.up) * num2; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(aimRay.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + if (step >= burstCount && IsKeyDownAuthority() && canCharge) + { + outer.SetNextState(new ChargeMegaBlaster()); + } + else + { + outer.SetNextState(new Idle()); + } + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write((byte)step); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + step = reader.ReadByte(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCorruptDisks.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCorruptDisks.cs new file mode 100644 index 0000000..8e2d804 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCorruptDisks.cs @@ -0,0 +1,123 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireCorruptDisks : BaseSkillState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public string muzzle; + + [SerializeField] + public float spread; + + [SerializeField] + public int projectileCount; + + [SerializeField] + public float yawPerProjectile; + + [SerializeField] + public float offsetPerProjectile; + + [SerializeField] + public float selfKnockbackForce; + + [SerializeField] + public float bonusPitch; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + duration = baseDuration / attackSpeedStat; + StartAimMode(duration + 2f); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(attackSoundString, base.gameObject); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + base.characterBody.characterMotor.ApplyForce((0f - selfKnockbackForce) * aimRay.direction); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + FireProjectiles(); + } + } + + private void FireProjectiles() + { + for (int i = 0; i < projectileCount; i++) + { + float num = (float)i - (float)(projectileCount - 1) / 2f; + float bonusYaw = num * yawPerProjectile; + float num2 = num * offsetPerProjectile; + Ray aimRay = GetAimRay(); + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, base.characterBody.spreadBloomAngle + spread, 1f, 1f, bonusYaw, bonusPitch); + Vector3 onUnitSphere = Random.onUnitSphere; + Vector3.ProjectOnPlane(onUnitSphere, aimRay.direction); + Quaternion rotation = Util.QuaternionSafeLookRotation(aimRay.direction, onUnitSphere); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = aimRay.origin + Vector3.Cross(aimRay.direction, Vector3.up) * num2; + fireProjectileInfo.rotation = rotation; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextState(new Idle()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCorruptHandBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCorruptHandBeam.cs new file mode 100644 index 0000000..ec35205 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCorruptHandBeam.cs @@ -0,0 +1,168 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireCorruptHandBeam : BaseSkillState +{ + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject beamVfxPrefab; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string exitSoundString; + + [SerializeField] + public float tickRate; + + [SerializeField] + public float damageCoefficientPerSecond; + + [SerializeField] + public float procCoefficientPerSecond; + + [SerializeField] + public float forcePerSecond; + + [SerializeField] + public float maxDistance; + + [SerializeField] + public float minDistance; + + [SerializeField] + public float bulletRadius; + + [SerializeField] + public float baseMinimumDuration = 2f; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float spreadBloomValue = 0.3f; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationEnterStateName; + + [SerializeField] + public string animationExitStateName; + + private GameObject blinkVfxInstance; + + private float minimumDuration; + + private float fireCountdown; + + public override void OnEnter() + { + base.OnEnter(); + minimumDuration = baseMinimumDuration / attackSpeedStat; + PlayAnimation(animationLayerName, animationEnterStateName); + Util.PlaySound(enterSoundString, base.gameObject); + blinkVfxInstance = Object.Instantiate(beamVfxPrefab); + blinkVfxInstance.transform.SetParent(base.characterBody.aimOriginTransform, worldPositionStays: false); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Slow50); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireCountdown -= GetDeltaTime(); + if (fireCountdown <= 0f) + { + fireCountdown = 1f / tickRate / attackSpeedStat; + FireBullet(); + } + base.characterBody.SetAimTimer(3f); + if ((bool)blinkVfxInstance) + { + Vector3 point = GetAimRay().GetPoint(maxDistance); + if (Util.CharacterRaycast(base.gameObject, GetAimRay(), out var hitInfo, maxDistance, LayerIndex.world.mask, QueryTriggerInteraction.UseGlobal)) + { + point = hitInfo.point; + } + blinkVfxInstance.transform.forward = point - blinkVfxInstance.transform.position; + } + if (((base.fixedAge >= minimumDuration && !IsKeyDownAuthority()) || base.characterBody.isSprinting) && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)blinkVfxInstance) + { + VfxKillBehavior.KillVfxObject(blinkVfxInstance); + } + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Slow50); + } + PlayAnimation(animationLayerName, animationExitStateName); + Util.PlaySound(exitSoundString, base.gameObject); + base.OnExit(); + } + + private void FireBullet() + { + Ray aimRay = GetAimRay(); + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.muzzleName = muzzle; + bulletAttack.maxDistance = Mathf.Lerp(minDistance, maxDistance, Random.value); + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = maxSpread; + bulletAttack.radius = bulletRadius; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.smartCollision = false; + bulletAttack.stopperMask = default(LayerMask); + bulletAttack.hitMask = LayerIndex.entityPrecise.mask; + bulletAttack.allowTrajectoryAimAssist = false; + bulletAttack.damage = damageCoefficientPerSecond * damageStat / tickRate; + bulletAttack.procCoefficient = procCoefficientPerSecond / tickRate; + bulletAttack.force = forcePerSecond / tickRate; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.Fire(); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCrabCannon.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCrabCannon.cs new file mode 100644 index 0000000..885ba42 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireCrabCannon.cs @@ -0,0 +1,114 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireCrabCannon : BaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public string muzzle; + + [SerializeField] + public int grenadeCountMax = 3; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public float fireDuration = 1f; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + private static float recoilAmplitude = 1f; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string perGrenadeSoundString; + + [SerializeField] + public float spreadBloomValue = 0.3f; + + private Transform modelTransform; + + private float duration; + + private float fireTimer; + + private int grenadeCount; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + modelTransform = GetModelTransform(); + StartAimMode(); + } + + public override void OnExit() + { + base.OnExit(); + } + + private void FireProjectile() + { + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(perGrenadeSoundString, base.gameObject); + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + base.characterBody.AddSpreadBloom(spreadBloomValue); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, maxSpread, 1f, 1f); + Vector3 onUnitSphere = Random.onUnitSphere; + Vector3.ProjectOnPlane(onUnitSphere, aimRay.direction); + Quaternion rotation = Util.QuaternionSafeLookRotation(aimRay.direction, onUnitSphere); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, rotation, base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + fireTimer -= GetDeltaTime(); + float num = fireDuration / attackSpeedStat / (float)grenadeCountMax; + if (fireTimer <= 0f && grenadeCount < grenadeCountMax) + { + FireProjectile(); + fireTimer += num; + grenadeCount++; + } + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireHandBeam.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireHandBeam.cs new file mode 100644 index 0000000..8e4fec7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireHandBeam.cs @@ -0,0 +1,122 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireHandBeam : BaseState +{ + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public GameObject tracerEffectPrefab; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float maxDistance; + + [SerializeField] + public float force; + + [SerializeField] + public int bulletCount; + + [SerializeField] + public float bulletRadius; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float spreadBloomValue = 0.3f; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + [SerializeField] + public float trajectoryAimAssistMultiplier = 0.75f; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Ray aimRay = GetAimRay(); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + AddRecoil(-1f * recoilAmplitude, -2f * recoilAmplitude, -0.5f * recoilAmplitude, 0.5f * recoilAmplitude); + StartAimMode(aimRay); + Util.PlaySound(attackSoundString, base.gameObject); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.muzzleName = muzzle; + bulletAttack.maxDistance = maxDistance; + bulletAttack.minSpread = 0f; + bulletAttack.maxSpread = base.characterBody.spreadBloomAngle; + bulletAttack.radius = bulletRadius; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.smartCollision = true; + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.procCoefficient = 1f / (float)bulletCount; + bulletAttack.force = force; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.damageType = DamageType.SlowOnHit; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.trajectoryAimAssistMultiplier = trajectoryAimAssistMultiplier; + bulletAttack.Fire(); + } + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterBase.cs new file mode 100644 index 0000000..9a57dd8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterBase.cs @@ -0,0 +1,111 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireMegaBlasterBase : BaseState +{ + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public string muzzle; + + [SerializeField] + public float spread; + + [SerializeField] + public float yawPerProjectile; + + [SerializeField] + public float selfKnockbackForce; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + Ray aimRay = GetAimRay(); + duration = baseDuration / attackSpeedStat; + StartAimMode(duration + 2f); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlaySound(attackSoundString, base.gameObject); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + FireProjectiles(); + } + base.characterBody.characterMotor.ApplyForce((0f - selfKnockbackForce) * aimRay.direction); + } + + private void FireProjectiles() + { + Ray ray = GetAimRay(); + TrajectoryAimAssist.ApplyTrajectoryAimAssist(ref ray, projectilePrefab, base.gameObject); + ray.direction = Util.ApplySpread(ray.direction, 0f, spread, 1f, 1f); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterBig.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterBig.cs new file mode 100644 index 0000000..a5b37bb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterBig.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireMegaBlasterBig : FireMegaBlasterBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterSmall.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterSmall.cs new file mode 100644 index 0000000..075ed6e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireMegaBlasterSmall.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireMegaBlasterSmall : FireMegaBlasterBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireRepulsion.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireRepulsion.cs new file mode 100644 index 0000000..6581d1a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireRepulsion.cs @@ -0,0 +1,220 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireRepulsion : BaseState +{ + [SerializeField] + public string sound; + + [SerializeField] + public string muzzle; + + [SerializeField] + public GameObject fireEffectPrefab; + + [SerializeField] + public float baseDuration; + + [SerializeField] + public float fieldOfView; + + [SerializeField] + public float backupDistance; + + [SerializeField] + public float maxKnockbackDistance; + + [SerializeField] + public float idealDistanceToPlaceTargets; + + [SerializeField] + public float liftVelocity; + + [SerializeField] + public float animationCrossfadeDuration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + [SerializeField] + public float damageMultiplier; + + [SerializeField] + public float maxProjectileReflectDistance; + + [SerializeField] + public GameObject tracerEffectPrefab; + + [SerializeField] + public float corruption; + + [SerializeField] + public BuffDef buffDef; + + [SerializeField] + public float buffDuration; + + public static AnimationCurve shoveSuitabilityCurve; + + private float duration; + + private Ray aimRay; + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + aimRay = GetAimRay(); + PlayCrossfade(animationLayerName, animationStateName, animationPlaybackParameterName, duration, animationCrossfadeDuration); + Util.PlaySound(sound, base.gameObject); + Vector3 origin = aimRay.origin; + Transform transform = FindModelChild(muzzle); + if ((bool)transform) + { + origin = transform.position; + } + EffectManager.SpawnEffect(fireEffectPrefab, new EffectData + { + origin = origin, + rotation = Quaternion.LookRotation(aimRay.direction) + }, transmit: false); + aimRay.origin -= aimRay.direction * backupDistance; + if (NetworkServer.active) + { + PushEnemies(); + ReflectProjectiles(); + VoidSurvivorController component = GetComponent(); + if ((bool)component) + { + component.AddCorruption(corruption); + } + } + } + + private void ReflectProjectiles() + { + Vector3 vector = (base.characterBody ? base.characterBody.corePosition : Vector3.zero); + TeamIndex teamIndex = (base.characterBody ? base.characterBody.teamComponent.teamIndex : TeamIndex.None); + float num = maxProjectileReflectDistance * maxProjectileReflectDistance; + List instancesList = InstanceTracker.GetInstancesList(); + List list = new List(); + int i = 0; + for (int count = instancesList.Count; i < count; i++) + { + ProjectileController projectileController = instancesList[i]; + if (projectileController.teamFilter.teamIndex != teamIndex && (projectileController.transform.position - vector).sqrMagnitude < num) + { + list.Add(projectileController); + } + } + int j = 0; + for (int count2 = list.Count; j < count2; j++) + { + ProjectileController projectileController2 = list[j]; + if (!projectileController2) + { + continue; + } + Vector3 position = projectileController2.transform.position; + Vector3 start = vector; + if ((bool)tracerEffectPrefab) + { + EffectData effectData = new EffectData + { + origin = position, + start = start + }; + EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true); + } + _ = projectileController2.owner; + CharacterBody component = projectileController2.owner.GetComponent(); + projectileController2.IgnoreCollisionsWithOwner(shouldIgnore: false); + projectileController2.Networkowner = base.gameObject; + projectileController2.teamFilter.teamIndex = base.characterBody.teamComponent.teamIndex; + ProjectileDamage component2 = projectileController2.GetComponent(); + if ((bool)component2) + { + component2.damage *= damageMultiplier; + } + Rigidbody component3 = projectileController2.GetComponent(); + if ((bool)component3) + { + Vector3 vector2 = component3.velocity * -1f; + if ((bool)component) + { + vector2 = component.corePosition - component3.transform.position; + } + component3.transform.forward = vector2; + component3.velocity = Vector3.RotateTowards(component3.velocity, vector2, float.PositiveInfinity, 0f); + } + } + } + + private void PushEnemies() + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.all; + bullseyeSearch.maxAngleFilter = fieldOfView * 0.5f; + bullseyeSearch.maxDistanceFilter = maxKnockbackDistance; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.filterByLoS = false; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + IEnumerable enumerable = bullseyeSearch.GetResults().Where(Util.IsValid).Distinct(default(HurtBox.EntityEqualityComparer)); + TeamIndex team = GetTeam(); + foreach (HurtBox item in enumerable) + { + if (FriendlyFireManager.ShouldSplashHitProceed(item.healthComponent, team)) + { + CharacterBody body = item.healthComponent.body; + AddDebuff(body); + body.RecalculateStats(); + _ = body.acceleration; + } + } + } + + protected virtual void AddDebuff(CharacterBody body) + { + body.AddTimedBuff(buffDef, buffDuration); + body.healthComponent.GetComponent()?.SetStun(-1f); + } + + protected virtual float CalculateDamage() + { + return 0f; + } + + protected virtual float CalculateProcCoefficient() + { + return 0f; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireTwinBlaster.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireTwinBlaster.cs new file mode 100644 index 0000000..81c5734 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/FireTwinBlaster.cs @@ -0,0 +1,111 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class FireTwinBlaster : BaseSkillState +{ + [SerializeField] + public GameObject projectile1Prefab; + + [SerializeField] + public GameObject projectile2Prefab; + + [SerializeField] + public GameObject muzzleflashEffectPrefab; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float damageCoefficient = 1.2f; + + [SerializeField] + public float force = 20f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float attackSoundPitchPerStep; + + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public string muzzle; + + [SerializeField] + public float spread; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParam; + + private float duration; + + private float interruptDuration; + + public int step; + + public override void OnEnter() + { + base.OnEnter(); + base.activatorSkillSlot = base.skillLocator.primary; + GetAimRay(); + duration = baseDuration / attackSpeedStat; + StartAimMode(duration + 2f); + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParam, duration); + Util.PlayAttackSpeedSound(attackSoundString, base.gameObject, 1f + (float)step * attackSoundPitchPerStep); + AddRecoil(-1f * recoilAmplitude, -1.5f * recoilAmplitude, -0.25f * recoilAmplitude, 0.25f * recoilAmplitude); + base.characterBody.AddSpreadBloom(bloom); + if ((bool)muzzleflashEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleflashEffectPrefab, base.gameObject, muzzle, transmit: false); + } + if (base.isAuthority) + { + FireProjectiles(); + } + } + + private void FireProjectiles() + { + Ray aimRay = GetAimRay(); + aimRay.direction = Util.ApplySpread(aimRay.direction, 0f, base.characterBody.spreadBloomAngle * spread, 1f, 1f); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = aimRay.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(aimRay.direction); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.damage = damageStat * damageCoefficient; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = Util.CheckRoll(critStat, base.characterBody.master); + fireProjectileInfo.projectilePrefab = projectile1Prefab; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + fireProjectileInfo.projectilePrefab = projectile2Prefab; + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ReadyMegaBlaster.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ReadyMegaBlaster.cs new file mode 100644 index 0000000..e9f5844 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/ReadyMegaBlaster.cs @@ -0,0 +1,65 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class ReadyMegaBlaster : BaseSkillState +{ + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public string muzzle; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string exitSoundString; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + private GameObject chargeEffectInstance; + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation(animationLayerName, animationStateName); + Transform transform = FindModelChild(muzzle); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(3f); + if (base.isAuthority && !IsKeyDownAuthority()) + { + outer.SetNextState(new FireMegaBlasterBig()); + } + } + + public override void OnExit() + { + Util.PlaySound(exitSoundString, base.gameObject); + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/Suppress.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/Suppress.cs new file mode 100644 index 0000000..77dab0a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/Suppress.cs @@ -0,0 +1,218 @@ +using System.Linq; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class Suppress : BaseSkillState +{ + [SerializeField] + public float minimumDuration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public float maxSearchAngleFilter; + + [SerializeField] + public float maxSearchDistance; + + [SerializeField] + public float idealDistance; + + [SerializeField] + public float springConstant; + + [SerializeField] + public float springMaxLength; + + [SerializeField] + public float damperConstant; + + [SerializeField] + public float suppressedTargetForceRadius; + + [SerializeField] + public GameObject suppressEffectPrefab; + + [SerializeField] + public string muzzle; + + [SerializeField] + public AnimationCurve forceSuitabilityCurve; + + [SerializeField] + public float damageCoefficientPerSecond; + + [SerializeField] + public float procCoefficientPerSecond; + + [SerializeField] + public float corruptionPerSecond; + + [SerializeField] + public float maxBreakDistance; + + [SerializeField] + public float tickRate; + + [SerializeField] + public bool applyForces; + + private GameObject suppressEffectInstance; + + private Transform idealFXTransform; + + private Transform targetFXTransform; + + private Transform muzzleTransform; + + private VoidSurvivorController voidSurvivorController; + + private CharacterBody targetBody; + + private float damageTickCountdown; + + public override void OnEnter() + { + base.OnEnter(); + targetBody = null; + voidSurvivorController = GetComponent(); + PlayAnimation(animationLayerName, animationStateName); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + muzzleTransform = component.FindChild(muzzle); + if ((bool)muzzleTransform && (bool)suppressEffectPrefab) + { + suppressEffectInstance = Object.Instantiate(suppressEffectPrefab, muzzleTransform.position, muzzleTransform.rotation); + suppressEffectInstance.transform.parent = base.characterBody.transform; + ChildLocator component2 = suppressEffectInstance.GetComponent(); + if ((bool)component2) + { + idealFXTransform = component2.FindChild("IdealFX"); + targetFXTransform = component2.FindChild("TargetFX"); + } + } + } + } + Ray aimRay = GetAimRay(); + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); + bullseyeSearch.maxAngleFilter = maxSearchAngleFilter; + bullseyeSearch.maxDistanceFilter = maxSearchDistance; + bullseyeSearch.searchOrigin = aimRay.origin; + bullseyeSearch.searchDirection = aimRay.direction; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle; + bullseyeSearch.filterByLoS = true; + bullseyeSearch.RefreshCandidates(); + bullseyeSearch.FilterOutGameObject(base.gameObject); + HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault(); + if ((bool)hurtBox) + { + Debug.LogFormat("Found target {0}", targetBody); + targetBody = hurtBox.healthComponent.body; + } + } + + public override void OnExit() + { + if ((bool)suppressEffectInstance) + { + EntityState.Destroy(suppressEffectInstance); + } + base.OnExit(); + } + + public override void Update() + { + base.Update(); + if ((bool)targetBody) + { + if ((bool)muzzleTransform) + { + suppressEffectInstance.transform.position = muzzleTransform.position; + } + if ((bool)idealFXTransform) + { + Ray aimRay = GetAimRay(); + _ = targetBody.corePosition; + Vector3 position = aimRay.origin + aimRay.direction * idealDistance; + idealFXTransform.position = position; + } + if ((bool)targetFXTransform) + { + targetFXTransform.position = targetBody.corePosition; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + base.characterBody.SetAimTimer(3f); + float deltaTime = GetDeltaTime(); + if (NetworkServer.active && (bool)targetBody) + { + Ray aimRay = GetAimRay(); + Vector3 corePosition = targetBody.corePosition; + Vector3 vector = aimRay.origin + aimRay.direction * idealDistance; + if (applyForces) + { + Vector3 vector2 = vector - corePosition; + float magnitude = vector2.magnitude; + Mathf.Clamp01(magnitude / suppressedTargetForceRadius); + Vector3 velocity; + float mass; + bool flag; + if ((bool)targetBody.characterMotor) + { + velocity = targetBody.characterMotor.velocity; + mass = targetBody.characterMotor.mass; + flag = !targetBody.characterMotor.isFlying; + } + else + { + Rigidbody obj = targetBody.rigidbody; + velocity = obj.velocity; + mass = obj.mass; + flag = obj.useGravity; + } + Vector3 vector3 = vector2.normalized * Mathf.Min(springMaxLength, magnitude) * springConstant * deltaTime; + Vector3 vector4 = -velocity * damperConstant * deltaTime; + Vector3 vector5 = (flag ? (Physics.gravity * deltaTime * mass) : Vector3.zero); + float num = forceSuitabilityCurve.Evaluate(mass); + targetBody.healthComponent.TakeDamageForce((vector3 + vector4) * num - vector5, alwaysApply: true, disableAirControlUntilCollision: true); + } + damageTickCountdown -= deltaTime; + if (damageTickCountdown <= 0f) + { + damageTickCountdown = 1f / tickRate; + DamageInfo damageInfo = new DamageInfo(); + damageInfo.attacker = base.gameObject; + damageInfo.procCoefficient = procCoefficientPerSecond / tickRate; + damageInfo.damage = damageCoefficientPerSecond * damageStat / tickRate; + damageInfo.crit = RollCrit(); + targetBody.healthComponent.TakeDamage(damageInfo); + voidSurvivorController.AddCorruption(corruptionPerSecond / tickRate); + } + } + if (base.isAuthority && (!targetBody || !targetBody.healthComponent.alive)) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee1.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee1.cs new file mode 100644 index 0000000..3d3284b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee1.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class SwingMelee1 : SwingMeleeBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee2.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee2.cs new file mode 100644 index 0000000..34ea689 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee2.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class SwingMelee2 : SwingMeleeBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee3.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee3.cs new file mode 100644 index 0000000..ef6fca5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMelee3.cs @@ -0,0 +1,5 @@ +namespace EntityStates.VoidSurvivor.Weapon; + +public class SwingMelee3 : SwingMeleeBase +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMeleeBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMeleeBase.cs new file mode 100644 index 0000000..bf3b662 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor.Weapon/SwingMeleeBase.cs @@ -0,0 +1,72 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivor.Weapon; + +public class SwingMeleeBase : BasicMeleeAttack +{ + [SerializeField] + public float recoilAmplitude; + + [SerializeField] + public float bloom; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string animationPlaybackRateParameter; + + protected override bool allowExitFire + { + get + { + if ((bool)base.characterBody) + { + return !base.characterBody.isSprinting; + } + return false; + } + } + + public override void OnEnter() + { + base.OnEnter(); + base.characterDirection.forward = GetAimRay().direction; + } + + public override void OnExit() + { + base.OnExit(); + } + + protected override void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + base.AuthorityModifyOverlapAttack(overlapAttack); + } + + protected override void PlayAnimation() + { + PlayAnimation(animationLayerName, animationStateName, animationPlaybackRateParameter, duration); + } + + protected override void OnMeleeHitAuthority() + { + base.OnMeleeHitAuthority(); + base.characterBody.AddSpreadBloom(bloom); + } + + protected override void BeginMeleeAttackEffect() + { + AddRecoil(-0.1f * recoilAmplitude, 0.1f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + base.BeginMeleeAttackEffect(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/CorruptionTransitionBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/CorruptionTransitionBase.cs new file mode 100644 index 0000000..0b3890f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/CorruptionTransitionBase.cs @@ -0,0 +1,136 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor; + +public class CorruptionTransitionBase : BaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationGroundStateName; + + [SerializeField] + public string animationAirStateName; + + [SerializeField] + public string animationPlaybackParameterName; + + [SerializeField] + public float animationCrossfadeDuration; + + [SerializeField] + public string entrySound; + + [SerializeField] + public GameObject chargeEffectPrefab; + + [SerializeField] + public GameObject completionEffectPrefab; + + [SerializeField] + public string effectmuzzle; + + [SerializeField] + public CharacterCameraParams cameraParams; + + [SerializeField] + public float dampingCoefficient; + + protected VoidSurvivorController voidSurvivorController; + + private GameObject chargeEffectInstance; + + private CameraTargetParams.CameraParamsOverrideHandle cameraParamsOverrideHandle; + + public override void OnEnter() + { + base.OnEnter(); + voidSurvivorController = GetComponent(); + PlayCrossfade(animationLayerName, base.characterMotor.isGrounded ? animationGroundStateName : animationAirStateName, animationPlaybackParameterName, duration, animationCrossfadeDuration); + Util.PlaySound(entrySound, base.gameObject); + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + StartCameraParamsOverride(duration); + Transform transform = FindModelChild(effectmuzzle); + if ((bool)transform && (bool)chargeEffectPrefab) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + if (base.isAuthority && (bool)voidSurvivorController) + { + voidSurvivorController.weaponStateMachine.SetNextStateToMain(); + } + } + + public override void OnExit() + { + EndCameraParamsOverride(0f); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + } + if ((bool)chargeEffectInstance) + { + EntityState.Destroy(chargeEffectInstance); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority) + { + base.characterMotor.velocity -= base.characterMotor.velocity * dampingCoefficient; + } + if (base.fixedAge >= duration && base.isAuthority) + { + OnFinishAuthority(); + outer.SetNextStateToMain(); + } + } + + public virtual void OnFinishAuthority() + { + EffectManager.SimpleMuzzleFlash(completionEffectPrefab, base.gameObject, effectmuzzle, transmit: true); + } + + protected void StartCameraParamsOverride(float transitionDuration) + { + if (!cameraParamsOverrideHandle.isValid) + { + cameraParamsOverrideHandle = base.cameraTargetParams.AddParamsOverride(new CameraTargetParams.CameraParamsOverrideRequest + { + cameraParamsData = cameraParams.data + }, transitionDuration); + } + } + + protected void EndCameraParamsOverride(float transitionDuration) + { + if (cameraParamsOverrideHandle.isValid) + { + base.cameraTargetParams.RemoveParamsOverride(cameraParamsOverrideHandle, transitionDuration); + cameraParamsOverrideHandle = default(CameraTargetParams.CameraParamsOverrideHandle); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/EnterCorruptionTransition.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/EnterCorruptionTransition.cs new file mode 100644 index 0000000..357ed09 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/EnterCorruptionTransition.cs @@ -0,0 +1,39 @@ +using EntityStates.VoidSurvivor.CorruptMode; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor; + +public class EnterCorruptionTransition : CorruptionTransitionBase +{ + [SerializeField] + public float lingeringInvincibilityDuration; + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)voidSurvivorController && NetworkServer.active) + { + voidSurvivorController.AddCorruption(100f); + } + } + + public override void OnFinishAuthority() + { + base.OnFinishAuthority(); + if ((bool)voidSurvivorController) + { + voidSurvivorController.corruptionModeStateMachine.SetNextState(new EntityStates.VoidSurvivor.CorruptMode.CorruptMode()); + } + } + + public override void OnExit() + { + base.OnExit(); + if (NetworkServer.active) + { + base.characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, lingeringInvincibilityDuration); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/ExitCorruptionTransition.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/ExitCorruptionTransition.cs new file mode 100644 index 0000000..e10e81d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/ExitCorruptionTransition.cs @@ -0,0 +1,25 @@ +using EntityStates.VoidSurvivor.CorruptMode; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor; + +public class ExitCorruptionTransition : CorruptionTransitionBase +{ + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)voidSurvivorController && NetworkServer.active) + { + voidSurvivorController.AddCorruption(-100f); + } + } + + public override void OnFinishAuthority() + { + base.OnFinishAuthority(); + if ((bool)voidSurvivorController) + { + voidSurvivorController.corruptionModeStateMachine.SetNextState(new UncorruptedMode()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/VoidBlinkBase.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/VoidBlinkBase.cs new file mode 100644 index 0000000..dd62e51 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivor/VoidBlinkBase.cs @@ -0,0 +1,169 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivor; + +public class VoidBlinkBase : BaseState +{ + public class VoidBlinkUp : VoidBlinkBase + { + } + + public class VoidBlinkDown : VoidBlinkBase + { + } + + private Transform modelTransform; + + [SerializeField] + public GameObject blinkEffectPrefab; + + [SerializeField] + public float duration = 0.3f; + + [SerializeField] + public float speedCoefficient = 25f; + + [SerializeField] + public string beginSoundString; + + [SerializeField] + public string endSoundString; + + [SerializeField] + public AnimationCurve forwardSpeed; + + [SerializeField] + public AnimationCurve upSpeed; + + [SerializeField] + public GameObject blinkVfxPrefab; + + [SerializeField] + public float overlayDuration; + + [SerializeField] + public Material overlayMaterial; + + private CharacterModel characterModel; + + private HurtBoxGroup hurtboxGroup; + + private Vector3 forwardVector; + + private GameObject blinkVfxInstance; + + private uint soundID; + + public override void OnEnter() + { + base.OnEnter(); + base.characterBody.bodyFlags |= CharacterBody.BodyFlags.OverheatImmune; + soundID = Util.PlaySound(beginSoundString, base.gameObject); + forwardVector = ((base.inputBank.moveVector == Vector3.zero) ? base.characterDirection.forward : base.inputBank.moveVector).normalized; + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + characterModel = modelTransform.GetComponent(); + hurtboxGroup = modelTransform.GetComponent(); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter + 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if (NetworkServer.active) + { + Util.CleanseBody(base.characterBody, removeDebuffs: true, removeBuffs: false, removeCooldownBuffs: false, removeDots: true, removeStun: true, removeNearbyProjectiles: false); + } + blinkVfxInstance = Object.Instantiate(blinkVfxPrefab); + blinkVfxInstance.transform.SetParent(base.transform, worldPositionStays: false); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + } + + protected virtual Vector3 GetBlinkVector() + { + return base.inputBank.aimDirection; + } + + private void CreateBlinkEffect(Vector3 origin) + { + EffectData effectData = new EffectData(); + effectData.rotation = Util.QuaternionSafeLookRotation(GetVelocity()); + effectData.origin = origin; + EffectManager.SpawnEffect(blinkEffectPrefab, effectData, transmit: false); + } + + private Vector3 GetVelocity() + { + float time = base.fixedAge / duration; + Vector3 vector = forwardSpeed.Evaluate(time) * forwardVector; + Vector3 vector2 = upSpeed.Evaluate(time) * Vector3.up; + return (vector + vector2) * speedCoefficient * moveSpeedStat; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.characterMotor && (bool)base.characterDirection) + { + if ((bool)base.characterMotor) + { + base.characterMotor.Motor.ForceUnground(); + } + Vector3 velocity = GetVelocity(); + base.characterMotor.velocity = velocity; + if ((bool)blinkVfxInstance) + { + blinkVfxInstance.transform.forward = velocity; + } + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + AkSoundEngine.StopPlayingID(soundID); + if (!outer.destroying) + { + Util.PlaySound(endSoundString, base.gameObject); + CreateBlinkEffect(Util.GetCorePosition(base.gameObject)); + } + if ((bool)blinkVfxInstance) + { + VfxKillBehavior.KillVfxObject(blinkVfxInstance); + } + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtboxGroup) + { + HurtBoxGroup hurtBoxGroup = hurtboxGroup; + int hurtBoxesDeactivatorCounter = hurtBoxGroup.hurtBoxesDeactivatorCounter - 1; + hurtBoxGroup.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + base.characterBody.bodyFlags &= ~CharacterBody.BodyFlags.OverheatImmune; + modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(modelTransform.gameObject); + temporaryOverlayInstance.duration = overlayDuration; + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); + temporaryOverlayInstance.destroyComponentOnEnd = true; + temporaryOverlayInstance.originalMaterial = overlayMaterial; + temporaryOverlayInstance.AddToCharacterModel(modelTransform.GetComponent()); + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Descent.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Descent.cs new file mode 100644 index 0000000..0e3b47c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Descent.cs @@ -0,0 +1,41 @@ +using EntityStates.SurvivorPod; +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivorPod; + +public class Descent : SurvivorPodBaseState +{ + [SerializeField] + public float duration; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && duration < base.fixedAge) + { + TransitionIntoNextState(); + } + } + + protected virtual void TransitionIntoNextState() + { + outer.SetNextState(new Landed()); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Landed.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Landed.cs new file mode 100644 index 0000000..aed2ba0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Landed.cs @@ -0,0 +1,79 @@ +using EntityStates.SurvivorPod; +using RoR2; +using UnityEngine; + +namespace EntityStates.VoidSurvivorPod; + +public class Landed : SurvivorPodBaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public string effectMuzzle; + + [SerializeField] + public GameObject openEffect; + + [SerializeField] + public string particleChildName; + + private ParticleSystem[] particles; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + base.vehicleSeat.handleVehicleExitRequestServer.AddCallback(HandleVehicleExitRequest); + ModelLocator component = GetComponent(); + if (!component || !component.modelTransform) + { + return; + } + ChildLocator component2 = component.modelTransform.GetComponent(); + if ((bool)component2) + { + Transform transform = component2.FindChild(particleChildName); + if ((bool)transform) + { + particles = transform.GetComponentsInChildren(); + transform.gameObject.SetActive(value: true); + } + } + } + + public override void FixedUpdate() + { + if (base.fixedAge > 0f) + { + base.survivorPodController.exitAllowed = true; + } + base.FixedUpdate(); + } + + private void HandleVehicleExitRequest(GameObject gameObject, ref bool? result) + { + base.survivorPodController.exitAllowed = false; + outer.SetNextState(new Release()); + result = true; + } + + public override void OnExit() + { + base.vehicleSeat.handleVehicleExitRequestServer.RemoveCallback(HandleVehicleExitRequest); + base.survivorPodController.exitAllowed = false; + EffectManager.SimpleMuzzleFlash(openEffect, base.gameObject, effectMuzzle, transmit: false); + ParticleSystem[] array = particles; + for (int i = 0; i < array.Length; i++) + { + array[i].Stop(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Release.cs b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Release.cs new file mode 100644 index 0000000..813388b --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.VoidSurvivorPod/Release.cs @@ -0,0 +1,51 @@ +using EntityStates.SurvivorPod; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.VoidSurvivorPod; + +public class Release : SurvivorPodBaseState +{ + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string enterSoundString; + + [SerializeField] + public float exitForceAmount; + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation(animationLayerName, animationStateName); + Util.PlaySound(enterSoundString, base.gameObject); + if ((bool)base.survivorPodController && NetworkServer.active && (bool)base.vehicleSeat && (bool)base.vehicleSeat.currentPassengerBody) + { + CharacterBody currentPassengerBody = base.vehicleSeat.currentPassengerBody; + base.vehicleSeat.EjectPassenger(currentPassengerBody.gameObject); + HealthComponent component = currentPassengerBody.GetComponent(); + if ((bool)component) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.attacker = base.gameObject; + damageInfo.force = Vector3.up * exitForceAmount; + damageInfo.position = currentPassengerBody.corePosition; + component.TakeDamageForce(damageInfo, alwaysApply: true); + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (NetworkServer.active && (!base.vehicleSeat || !base.vehicleSeat.currentPassengerBody)) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture.Weapon/ChargeWindblade.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture.Weapon/ChargeWindblade.cs new file mode 100644 index 0000000..dd9a9cc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture.Weapon/ChargeWindblade.cs @@ -0,0 +1,85 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Vulture.Weapon; + +public class ChargeWindblade : BaseSkillState +{ + public static float baseDuration; + + public static string muzzleString; + + public static GameObject chargeEffectPrefab; + + public static string soundString; + + private float duration; + + private GameObject chargeEffectInstance; + + protected EffectManagerHelper _emh_chargeEffectInstance; + + private static int ChargeWindbladeStateHash = Animator.StringToHash("ChargeWindblade"); + + private static int ChargeWindbladeParamHash = Animator.StringToHash("ChargeWindblade.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffectInstance = null; + _emh_chargeEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", ChargeWindbladeStateHash, ChargeWindbladeParamHash, duration); + Util.PlaySound(soundString, base.gameObject); + base.characterBody.SetAimTimer(3f); + Transform transform = FindModelChild(muzzleString); + if ((bool)transform && (bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffectInstance = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance = _emh_chargeEffectInstance.gameObject; + } + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component = chargeEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = duration; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new FireWindblade()); + } + } + + public override void OnExit() + { + if (_emh_chargeEffectInstance != null && _emh_chargeEffectInstance.OwningPool != null) + { + _emh_chargeEffectInstance.OwningPool.ReturnObject(_emh_chargeEffectInstance); + } + else if (chargeEffectInstance != null) + { + EntityState.Destroy(chargeEffectInstance); + } + chargeEffectInstance = null; + _emh_chargeEffectInstance = null; + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture.Weapon/FireWindblade.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture.Weapon/FireWindblade.cs new file mode 100644 index 0000000..5c052f0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture.Weapon/FireWindblade.cs @@ -0,0 +1,56 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates.Vulture.Weapon; + +public class FireWindblade : BaseSkillState +{ + public static float baseDuration; + + public static string muzzleString; + + public static GameObject muzzleEffectPrefab; + + public static GameObject projectilePrefab; + + public static float damageCoefficient = 1.2f; + + public static float force = 20f; + + public static string soundString; + + private float duration; + + private static int FireWindbladeStateHash = Animator.StringToHash("FireWindblade"); + + private static int FireWindbladeParamHash = Animator.StringToHash("FireWindblade.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + PlayAnimation("Gesture, Additive", FireWindbladeStateHash, FireWindbladeParamHash, duration); + Util.PlaySound(soundString, base.gameObject); + if ((bool)muzzleEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(muzzleEffectPrefab, base.gameObject, muzzleString, transmit: false); + } + Ray aimRay = GetAimRay(); + if (base.isAuthority) + { + Quaternion quaternion = Util.QuaternionSafeLookRotation(aimRay.direction); + Quaternion quaternion2 = Quaternion.AngleAxis(Random.Range(0f, 360f), aimRay.direction); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, quaternion2 * quaternion, base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture/FallingDeath.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture/FallingDeath.cs new file mode 100644 index 0000000..67ffa69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture/FallingDeath.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace EntityStates.Vulture; + +public class FallingDeath : GenericCharacterDeath +{ + private Animator animator; + + private static int isGroundedParamHash = Animator.StringToHash("isGrounded"); + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity.y = 0f; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)animator) + { + animator.SetBool(isGroundedParamHash, base.characterMotor.isGrounded); + return; + } + animator = GetModelAnimator(); + if ((bool)animator) + { + int layerIndex = animator.GetLayerIndex("FlyOverride"); + animator.SetLayerWeight(layerIndex, 0f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture/Fly.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture/Fly.cs new file mode 100644 index 0000000..e1dde55 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture/Fly.cs @@ -0,0 +1,74 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates.Vulture; + +public class Fly : VultureModeState +{ + public static SkillDef landingSkill; + + public static float launchSpeed; + + public static GameObject jumpEffectPrefab; + + public static string jumpEffectMuzzleString; + + private static int JumpStateHash = Animator.StringToHash("Jump"); + + public override void OnEnter() + { + base.OnEnter(); + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount++; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount++; + characterFlightParameterProvider.flightParameters = flightParameters; + } + if ((bool)base.characterMotor) + { + base.characterMotor.velocity.y = launchSpeed; + base.characterMotor.Motor.ForceUnground(); + } + PlayAnimation("Body", JumpStateHash); + if ((bool)base.activatorSkillSlot) + { + base.activatorSkillSlot.SetSkillOverride(this, landingSkill, GenericSkill.SkillOverridePriority.Contextual); + } + if ((bool)jumpEffectPrefab) + { + EffectManager.SimpleMuzzleFlash(jumpEffectPrefab, base.gameObject, jumpEffectMuzzleString, transmit: false); + } + } + + public override void OnExit() + { + if ((bool)base.activatorSkillSlot) + { + base.activatorSkillSlot.UnsetSkillOverride(this, landingSkill, GenericSkill.SkillOverridePriority.Contextual); + } + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount--; + characterFlightParameterProvider.flightParameters = flightParameters; + } + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount--; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = true; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture/FlyToLand.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture/FlyToLand.cs new file mode 100644 index 0000000..0b09ab1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture/FlyToLand.cs @@ -0,0 +1,116 @@ +using RoR2; +using RoR2.Navigation; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Vulture; + +public class FlyToLand : BaseSkillState +{ + private float duration; + + private Vector3 targetPosition; + + public static float speedMultiplier; + + private ICharacterGravityParameterProvider characterGravityParameterProvider; + + private ICharacterFlightParameterProvider characterFlightParameterProvider; + + public override void OnEnter() + { + base.OnEnter(); + characterGravityParameterProvider = base.gameObject.GetComponent(); + characterFlightParameterProvider = base.gameObject.GetComponent(); + Vector3 footPosition = GetFootPosition(); + if (base.isAuthority) + { + bool flag = false; + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + if ((bool)groundNodes) + { + NodeGraph.NodeIndex nodeIndex = groundNodes.FindClosestNodeWithFlagConditions(base.transform.position, base.characterBody.hullClassification, NodeFlags.None, NodeFlags.None, preventOverhead: false); + flag = nodeIndex != NodeGraph.NodeIndex.invalid && groundNodes.GetNodePosition(nodeIndex, out targetPosition); + } + if (!flag) + { + outer.SetNextState(new Fly + { + activatorSkillSlot = base.activatorSkillSlot + }); + duration = 0f; + targetPosition = footPosition; + return; + } + } + Vector3 vector = targetPosition - footPosition; + float num = moveSpeedStat * speedMultiplier; + duration = vector.magnitude / num; + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount++; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount++; + characterFlightParameterProvider.flightParameters = flightParameters; + } + } + + private Vector3 GetFootPosition() + { + if ((bool)base.characterBody) + { + return base.characterBody.footPosition; + } + return base.transform.position; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + Vector3 footPosition = GetFootPosition(); + base.characterMotor.moveDirection = (targetPosition - footPosition).normalized * speedMultiplier; + if (base.isAuthority && (base.characterMotor.isGrounded || duration <= base.fixedAge)) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount--; + characterFlightParameterProvider.flightParameters = flightParameters; + } + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount--; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.SetFloat("Flying", 0f); + } + base.OnExit(); + } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + writer.Write(targetPosition); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + targetPosition = reader.ReadVector3(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture/Land.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture/Land.cs new file mode 100644 index 0000000..ac30a6d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture/Land.cs @@ -0,0 +1,9 @@ +namespace EntityStates.Vulture; + +public class Land : VultureModeState +{ + public override void OnEnter() + { + base.OnEnter(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture/SpawnState.cs new file mode 100644 index 0000000..381b0fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture/SpawnState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Vulture; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Vulture/VultureModeState.cs b/ilspy_dump/ror2_csproj/EntityStates.Vulture/VultureModeState.cs new file mode 100644 index 0000000..6d5e046 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Vulture/VultureModeState.cs @@ -0,0 +1,66 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Vulture; + +public class VultureModeState : BaseSkillState +{ + [SerializeField] + public float mecanimTransitionDuration; + + [SerializeField] + public float flyOverrideMecanimLayerWeight; + + [SerializeField] + public float movementSpeedMultiplier; + + [SerializeField] + public string enterSoundString; + + protected Animator animator; + + protected int flyOverrideLayer; + + protected ICharacterGravityParameterProvider characterGravityParameterProvider; + + protected ICharacterFlightParameterProvider characterFlightParameterProvider; + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + characterGravityParameterProvider = base.gameObject.GetComponent(); + characterFlightParameterProvider = base.gameObject.GetComponent(); + if ((bool)animator) + { + flyOverrideLayer = animator.GetLayerIndex("FlyOverride"); + } + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = movementSpeedMultiplier; + } + if ((bool)base.modelLocator) + { + base.modelLocator.normalizeToFloor = false; + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void Update() + { + base.Update(); + if ((bool)animator) + { + animator.SetLayerWeight(flyOverrideLayer, Util.Remap(Mathf.Clamp01(base.age / mecanimTransitionDuration), 0f, 1f, 1f - flyOverrideMecanimLayerWeight, flyOverrideMecanimLayerWeight)); + } + } + + public override void OnExit() + { + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/ChargeEmbers.cs b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/ChargeEmbers.cs new file mode 100644 index 0000000..00f00aa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/ChargeEmbers.cs @@ -0,0 +1,190 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Wisp1Monster; + +public class ChargeEmbers : BaseState +{ + public static float baseDuration = 3f; + + public static GameObject chargeEffectPrefab; + + public static GameObject laserEffectPrefab; + + public static string attackString; + + private float duration; + + private float stopwatch; + + private uint soundID; + + private GameObject chargeEffectInstance; + + private GameObject laserEffectInstance; + + private LineRenderer laserEffectInstanceLineRenderer; + + private bool lineRendererNull; + + protected EffectManagerHelper _emh_chargeEffect; + + protected EffectManagerHelper _emh_laserEffect; + + private Color startColor = Color.white; + + private static int ChargeAttack1StateHash = Animator.StringToHash("ChargeAttack1"); + + private static int ChargeAttack1ParamHash = Animator.StringToHash("ChargeAttack1.playbackRate"); + + public override void Reset() + { + base.Reset(); + duration = 0f; + chargeEffectInstance = null; + laserEffectInstance = null; + laserEffectInstanceLineRenderer = null; + lineRendererNull = true; + _emh_chargeEffect = null; + _emh_laserEffect = null; + startColor = Color.white; + } + + public override void OnEnter() + { + base.OnEnter(); + SetAIUpdateFrequency(alwaysUpdate: true); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + soundID = Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("Muzzle"); + if ((bool)transform) + { + if ((bool)chargeEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(chargeEffectPrefab)) + { + chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_chargeEffect = EffectManager.GetAndActivatePooledEffect(chargeEffectPrefab, transform.position, transform.rotation); + chargeEffectInstance = _emh_chargeEffect.gameObject; + } + chargeEffectInstance.transform.parent = transform; + ScaleParticleSystemDuration component2 = chargeEffectInstance.GetComponent(); + if ((bool)component2) + { + component2.newDuration = duration; + } + } + if ((bool)laserEffectPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(laserEffectPrefab)) + { + laserEffectInstance = Object.Instantiate(laserEffectPrefab, transform.position, transform.rotation); + } + else + { + _emh_laserEffect = EffectManager.GetAndActivatePooledEffect(laserEffectPrefab, transform.position, transform.rotation); + laserEffectInstance = _emh_laserEffect.gameObject; + } + laserEffectInstance.transform.parent = transform; + laserEffectInstanceLineRenderer = laserEffectInstance.GetComponent(); + lineRendererNull = false; + } + } + } + } + PlayAnimation("Body", ChargeAttack1StateHash, ChargeAttack1ParamHash, duration); + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + } + + public override void OnExit() + { + base.OnExit(); + SetAIUpdateFrequency(alwaysUpdate: false); + AkSoundEngine.StopPlayingID(soundID); + if ((bool)chargeEffectInstance) + { + if (!EffectManager.UsePools) + { + EntityState.Destroy(chargeEffectInstance); + } + else if (_emh_chargeEffect != null && _emh_chargeEffect.OwningPool != null) + { + _emh_chargeEffect.OwningPool.ReturnObject(_emh_chargeEffect); + } + else + { + EntityState.Destroy(chargeEffectInstance); + } + chargeEffectInstance = null; + _emh_chargeEffect = null; + } + if ((bool)laserEffectInstance) + { + if (!EffectManager.UsePools) + { + EntityState.Destroy(laserEffectInstance); + } + else if (_emh_laserEffect != null && _emh_laserEffect.OwningPool != null) + { + _emh_laserEffect.OwningPool.ReturnObject(_emh_laserEffect); + } + else + { + EntityState.Destroy(laserEffectInstance); + } + laserEffectInstance = null; + _emh_laserEffect = null; + lineRendererNull = true; + } + } + + public override void Update() + { + base.Update(); + if (!lineRendererNull) + { + if (!laserEffectInstanceLineRenderer) + { + lineRendererNull = true; + return; + } + Ray aimRay = GetAimRay(); + float distance = 50f; + Vector3 origin = aimRay.origin; + Vector3 point = aimRay.GetPoint(distance); + laserEffectInstanceLineRenderer.SetPosition(0, origin); + laserEffectInstanceLineRenderer.SetPosition(1, point); + startColor.a = stopwatch / duration; + laserEffectInstanceLineRenderer.startColor = startColor; + laserEffectInstanceLineRenderer.endColor = Color.clear; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextState(new FireEmbers()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/DeathState.cs b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/DeathState.cs new file mode 100644 index 0000000..b9a8336 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/DeathState.cs @@ -0,0 +1,42 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates.Wisp1Monster; + +public class DeathState : GenericCharacterDeath +{ + public static GameObject initialExplosion; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.modelLocator) + { + if ((bool)base.modelLocator.modelBaseTransform) + { + EntityState.Destroy(base.modelLocator.modelBaseTransform.gameObject); + } + if ((bool)base.modelLocator.modelTransform) + { + EntityState.Destroy(base.modelLocator.modelTransform.gameObject); + } + } + if (!EffectManager.ShouldUsePooledEffect(initialExplosion)) + { + Object.Instantiate(initialExplosion, base.transform.position, base.transform.rotation); + } + else + { + EffectManager.SpawnEffect(initialExplosion, new EffectData + { + origin = base.transform.position, + rotation = base.transform.rotation + }, transmit: false); + } + if (NetworkServer.active) + { + EntityState.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/FireEmbers.cs b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/FireEmbers.cs new file mode 100644 index 0000000..f106f36 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/FireEmbers.cs @@ -0,0 +1,89 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Wisp1Monster; + +public class FireEmbers : BaseState +{ + public static GameObject effectPrefab; + + public static GameObject hitEffectPrefab; + + public static GameObject tracerEffectPrefab; + + public static float damageCoefficient; + + public static float force; + + public static float minSpread; + + public static float maxSpread; + + public static int bulletCount; + + public static float baseDuration = 2f; + + public static string attackString; + + private float duration; + + private static int FireAttack1StateHash = Animator.StringToHash("FireAttack1"); + + private static int FireAttack1ParamHash = Animator.StringToHash("FireAttack1.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlayAttackSpeedSound(attackString, base.gameObject, attackSpeedStat); + Ray aimRay = GetAimRay(); + StartAimMode(aimRay); + PlayAnimation("Body", FireAttack1StateHash, FireAttack1ParamHash, duration); + string muzzleName = ""; + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, muzzleName, transmit: false); + } + if (base.isAuthority) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = base.gameObject; + bulletAttack.weapon = base.gameObject; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = minSpread; + bulletAttack.maxSpread = maxSpread; + bulletAttack.bulletCount = ((bulletCount > 0) ? ((uint)bulletCount) : 0u); + bulletAttack.damage = damageCoefficient * damageStat; + bulletAttack.force = force; + bulletAttack.tracerEffectPrefab = tracerEffectPrefab; + bulletAttack.muzzleName = muzzleName; + bulletAttack.hitEffectPrefab = hitEffectPrefab; + bulletAttack.isCrit = Util.CheckRoll(critStat, base.characterBody.master); + bulletAttack.falloffModel = BulletAttack.FalloffModel.DefaultBullet; + bulletAttack.HitEffectNormal = false; + bulletAttack.radius = 0.5f; + bulletAttack.procCoefficient = 1f / (float)bulletCount; + bulletAttack.Fire(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/SpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/SpawnState.cs new file mode 100644 index 0000000..5a9a39f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates.Wisp1Monster/SpawnState.cs @@ -0,0 +1,36 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates.Wisp1Monster; + +public class SpawnState : BaseState +{ + public static float duration = 4f; + + public static string spawnSoundString; + + private static int SpawnStateHash = Animator.StringToHash("Spawn"); + + private static int SpawnParamHash = Animator.StringToHash("Spawn.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + PlayAnimation("Body", SpawnStateHash, SpawnParamHash, duration); + Util.PlaySound(spawnSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/AimThrowableBase.cs b/ilspy_dump/ror2_csproj/EntityStates/AimThrowableBase.cs new file mode 100644 index 0000000..e17e418 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/AimThrowableBase.cs @@ -0,0 +1,350 @@ +using System; +using RoR2; +using RoR2.Projectile; +using Unity.Collections; +using Unity.Jobs; +using UnityEngine; + +namespace EntityStates; + +public abstract class AimThrowableBase : BaseSkillState +{ + private struct CalculateArcPointsJob : IJobParallelFor, IDisposable + { + [ReadOnly] + private Vector3 origin; + + [ReadOnly] + private Vector3 velocity; + + [ReadOnly] + private float indexMultiplier; + + [ReadOnly] + private float gravity; + + [WriteOnly] + public NativeArray outputPositions; + + public void SetParameters(Vector3 origin, Vector3 velocity, float totalTravelTime, int positionCount, float gravity) + { + this.origin = origin; + this.velocity = velocity; + if (outputPositions.Length != positionCount) + { + if (outputPositions.IsCreated) + { + outputPositions.Dispose(); + } + outputPositions = new NativeArray(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + } + indexMultiplier = totalTravelTime / (float)(positionCount - 1); + this.gravity = gravity; + } + + public void Dispose() + { + if (outputPositions.IsCreated) + { + outputPositions.Dispose(); + } + } + + public void Execute(int index) + { + float t = (float)index * indexMultiplier; + outputPositions[index] = Trajectory.CalculatePositionAtTime(origin, velocity, t, gravity); + } + } + + protected struct TrajectoryInfo + { + public Ray finalRay; + + public Vector3 hitPoint; + + public Vector3 hitNormal; + + public float travelTime; + + public float speedOverride; + } + + [SerializeField] + public float maxDistance; + + [SerializeField] + public float rayRadius; + + [SerializeField] + public GameObject arcVisualizerPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public GameObject endpointVisualizerPrefab; + + [SerializeField] + public float endpointVisualizerRadiusScale; + + [SerializeField] + public bool setFuse; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float baseMinimumDuration; + + protected LineRenderer arcVisualizerLineRenderer; + + protected Transform endpointVisualizerTransform; + + protected float projectileBaseSpeed; + + protected float detonationRadius; + + protected float minimumDuration; + + protected bool useGravity; + + private CalculateArcPointsJob calculateArcPointsJob; + + private JobHandle calculateArcPointsJobHandle; + + private Vector3[] pointsBuffer = Array.Empty(); + + private Action completeArcPointsVisualizerJobMethod; + + protected TrajectoryInfo currentTrajectoryInfo; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)arcVisualizerPrefab) + { + arcVisualizerLineRenderer = UnityEngine.Object.Instantiate(arcVisualizerPrefab, base.transform.position, Quaternion.identity).GetComponent(); + calculateArcPointsJob = default(CalculateArcPointsJob); + completeArcPointsVisualizerJobMethod = CompleteArcVisualizerJob; + RoR2Application.onLateUpdate += completeArcPointsVisualizerJobMethod; + } + if ((bool)endpointVisualizerPrefab) + { + endpointVisualizerTransform = UnityEngine.Object.Instantiate(endpointVisualizerPrefab, base.transform.position, Quaternion.identity).transform; + } + if ((bool)base.characterBody) + { + base.characterBody.hideCrosshair = true; + } + ProjectileSimple component = projectilePrefab.GetComponent(); + if ((bool)component) + { + projectileBaseSpeed = component.velocity; + } + Rigidbody component2 = projectilePrefab.GetComponent(); + if ((bool)component2) + { + useGravity = component2.useGravity; + } + minimumDuration = baseMinimumDuration / attackSpeedStat; + ProjectileImpactExplosion component3 = projectilePrefab.GetComponent(); + if ((bool)component3) + { + detonationRadius = component3.blastRadius; + if ((bool)endpointVisualizerTransform) + { + endpointVisualizerTransform.localScale = new Vector3(detonationRadius, detonationRadius, detonationRadius); + } + } + UpdateVisualizers(currentTrajectoryInfo); + SceneCamera.onSceneCameraPreRender += OnPreRenderSceneCam; + } + + public override void OnExit() + { + SceneCamera.onSceneCameraPreRender -= OnPreRenderSceneCam; + if (!outer.destroying) + { + if (base.isAuthority) + { + FireProjectile(); + } + OnProjectileFiredLocal(); + } + if ((bool)base.characterBody) + { + base.characterBody.hideCrosshair = false; + } + calculateArcPointsJobHandle.Complete(); + if ((bool)arcVisualizerLineRenderer) + { + EntityState.Destroy(arcVisualizerLineRenderer.gameObject); + arcVisualizerLineRenderer = null; + } + if (completeArcPointsVisualizerJobMethod != null) + { + RoR2Application.onLateUpdate -= completeArcPointsVisualizerJobMethod; + completeArcPointsVisualizerJobMethod = null; + } + calculateArcPointsJob.Dispose(); + pointsBuffer = Array.Empty(); + if ((bool)endpointVisualizerTransform) + { + EntityState.Destroy(endpointVisualizerTransform.gameObject); + endpointVisualizerTransform = null; + } + base.OnExit(); + } + + protected virtual bool KeyIsDown() + { + return IsKeyDownAuthority(); + } + + protected virtual void OnProjectileFiredLocal() + { + } + + protected virtual void FireProjectile() + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.position = currentTrajectoryInfo.finalRay.origin; + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(currentTrajectoryInfo.finalRay.direction, Vector3.up); + fireProjectileInfo.speedOverride = currentTrajectoryInfo.speedOverride; + fireProjectileInfo.damage = damageCoefficient * damageStat; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + if (setFuse) + { + fireProjectileInfo2.fuseOverride = currentTrajectoryInfo.travelTime; + } + ModifyProjectile(ref fireProjectileInfo2); + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + + protected virtual void ModifyProjectile(ref FireProjectileInfo fireProjectileInfo) + { + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && !KeyIsDown() && base.fixedAge >= minimumDuration) + { + UpdateTrajectoryInfo(out currentTrajectoryInfo); + EntityState entityState = PickNextState(); + if (entityState != null) + { + outer.SetNextState(entityState); + } + else + { + outer.SetNextStateToMain(); + } + } + } + + protected virtual EntityState PickNextState() + { + return null; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } + + public override void Update() + { + base.Update(); + UpdateTrajectoryInfo(out currentTrajectoryInfo); + UpdateVisualizers(currentTrajectoryInfo); + } + + protected virtual void UpdateTrajectoryInfo(out TrajectoryInfo dest) + { + dest = default(TrajectoryInfo); + Ray aimRay = GetAimRay(); + RaycastHit hitInfo = default(RaycastHit); + bool flag = false; + if (rayRadius > 0f && Util.CharacterSpherecast(base.gameObject, aimRay, rayRadius, out hitInfo, maxDistance, LayerIndex.CommonMasks.bullet, QueryTriggerInteraction.UseGlobal) && (bool)hitInfo.collider.GetComponent()) + { + flag = true; + } + if (!flag) + { + flag = Util.CharacterRaycast(base.gameObject, aimRay, out hitInfo, maxDistance, LayerIndex.CommonMasks.bullet, QueryTriggerInteraction.UseGlobal); + } + if (flag) + { + dest.hitPoint = hitInfo.point; + dest.hitNormal = hitInfo.normal; + } + else + { + dest.hitPoint = aimRay.GetPoint(maxDistance); + dest.hitNormal = -aimRay.direction; + } + Vector3 vector = dest.hitPoint - aimRay.origin; + if (useGravity) + { + float num = projectileBaseSpeed; + Vector2 vector2 = new Vector2(vector.x, vector.z); + float magnitude = vector2.magnitude; + float y = Trajectory.CalculateInitialYSpeed(magnitude / num, vector.y); + Vector3 vector3 = new Vector3(vector2.x / magnitude * num, y, vector2.y / magnitude * num); + dest.speedOverride = vector3.magnitude; + dest.finalRay = new Ray(aimRay.origin, vector3 / dest.speedOverride); + dest.travelTime = Trajectory.CalculateGroundTravelTime(num, magnitude); + } + else + { + dest.speedOverride = projectileBaseSpeed; + dest.finalRay = aimRay; + dest.travelTime = projectileBaseSpeed / vector.magnitude; + } + } + + private void CompleteArcVisualizerJob() + { + calculateArcPointsJobHandle.Complete(); + if ((bool)arcVisualizerLineRenderer) + { + Array.Resize(ref pointsBuffer, calculateArcPointsJob.outputPositions.Length); + calculateArcPointsJob.outputPositions.CopyTo(pointsBuffer); + arcVisualizerLineRenderer.SetPositions(pointsBuffer); + } + } + + private void UpdateVisualizers(TrajectoryInfo trajectoryInfo) + { + if ((bool)arcVisualizerLineRenderer && calculateArcPointsJobHandle.IsCompleted) + { + calculateArcPointsJob.SetParameters(trajectoryInfo.finalRay.origin, trajectoryInfo.finalRay.direction * trajectoryInfo.speedOverride, trajectoryInfo.travelTime, arcVisualizerLineRenderer.positionCount, useGravity ? Physics.gravity.y : 0f); + calculateArcPointsJobHandle = calculateArcPointsJob.Schedule(calculateArcPointsJob.outputPositions.Length, 32); + } + if ((bool)endpointVisualizerTransform) + { + endpointVisualizerTransform.SetPositionAndRotation(trajectoryInfo.hitPoint, Util.QuaternionSafeLookRotation(trajectoryInfo.hitNormal)); + if (!endpointVisualizerRadiusScale.Equals(0f)) + { + endpointVisualizerTransform.localScale = new Vector3(endpointVisualizerRadiusScale, endpointVisualizerRadiusScale, endpointVisualizerRadiusScale); + } + } + } + + private void OnPreRenderSceneCam(SceneCamera sceneCam) + { + if ((bool)arcVisualizerLineRenderer) + { + arcVisualizerLineRenderer.renderingLayerMask = ((sceneCam.cameraRigController.target == base.gameObject) ? 1u : 0u); + } + if ((bool)endpointVisualizerTransform) + { + endpointVisualizerTransform.gameObject.layer = ((sceneCam.cameraRigController.target == base.gameObject) ? LayerIndex.defaultLayer.intVal : LayerIndex.noDraw.intVal); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/AnimatedJump.cs b/ilspy_dump/ror2_csproj/EntityStates/AnimatedJump.cs new file mode 100644 index 0000000..b71f4d9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/AnimatedJump.cs @@ -0,0 +1,44 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class AnimatedJump : BaseState +{ + private float duration; + + private bool hasInputJump; + + public override void OnEnter() + { + base.OnEnter(); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.CrossFadeInFixedTime("AnimatedJump", 0.25f); + modelAnimator.Update(0f); + duration = modelAnimator.GetNextAnimatorStateInfo(layerIndex).length; + AimAnimator component = modelAnimator.GetComponent(); + if ((bool)component) + { + component.enabled = true; + } + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration / 2f && base.isAuthority && !hasInputJump) + { + hasInputJump = true; + base.characterMotor.moveDirection = base.inputBank.moveVector; + GenericCharacterMain.ApplyJumpVelocity(base.characterMotor, base.characterBody, 1f, 1f); + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BaseBodyAttachmentState.cs b/ilspy_dump/ror2_csproj/EntityStates/BaseBodyAttachmentState.cs new file mode 100644 index 0000000..1ec44fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BaseBodyAttachmentState.cs @@ -0,0 +1,17 @@ +using RoR2; + +namespace EntityStates; + +public class BaseBodyAttachmentState : EntityState +{ + protected NetworkedBodyAttachment bodyAttachment { get; private set; } + + protected CharacterBody attachedBody { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + bodyAttachment = GetComponent(); + attachedBody = (bodyAttachment ? bodyAttachment.attachedBody : null); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BaseCharacterMain.cs b/ilspy_dump/ror2_csproj/EntityStates/BaseCharacterMain.cs new file mode 100644 index 0000000..880037a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BaseCharacterMain.cs @@ -0,0 +1,232 @@ +using System.Runtime.CompilerServices; +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class BaseCharacterMain : BaseState +{ + private RootMotionAccumulator rootMotionAccumulator; + + private Vector3 previousPosition; + + protected CharacterAnimParamAvailability characterAnimParamAvailability; + + private CharacterAnimatorWalkParamCalculator animatorWalkParamCalculator; + + protected BodyAnimatorSmoothingParameters.SmoothingParameters smoothingParameters; + + protected bool useRootMotion; + + private bool wasGrounded; + + private float lastYSpeed; + + protected bool hasCharacterMotor; + + protected bool hasCharacterDirection; + + protected bool hasCharacterBody; + + protected bool hasRailMotor; + + protected bool hasCameraTargetParams; + + protected bool hasSkillLocator; + + protected bool hasModelAnimator; + + protected bool hasInputBank; + + protected bool hasRootMotionAccumulator; + + protected Animator modelAnimator { get; private set; } + + protected Vector3 estimatedVelocity { get; private set; } + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + rootMotionAccumulator = GetModelRootMotionAccumulator(); + if ((bool)rootMotionAccumulator) + { + rootMotionAccumulator.ExtractRootMotion(); + } + GetBodyAnimatorSmoothingParameters(out smoothingParameters); + previousPosition = base.transform.position; + hasCharacterMotor = base.characterMotor; + hasCharacterDirection = base.characterDirection; + hasCharacterBody = base.characterBody; + hasRailMotor = base.railMotor; + hasCameraTargetParams = base.cameraTargetParams; + hasSkillLocator = base.skillLocator; + hasModelAnimator = modelAnimator; + hasInputBank = base.inputBank; + hasRootMotionAccumulator = rootMotionAccumulator; + if ((bool)modelAnimator) + { + characterAnimParamAvailability = CharacterAnimParamAvailability.FromAnimator(modelAnimator); + int layerIndex = modelAnimator.GetLayerIndex("Body"); + if (characterAnimParamAvailability.isGrounded) + { + wasGrounded = base.isGrounded; + modelAnimator.SetBool(AnimationParameters.isGrounded, wasGrounded); + } + if (base.isGrounded || !hasCharacterMotor) + { + modelAnimator.CrossFadeInFixedTime("Idle", 0.1f, layerIndex); + } + else + { + modelAnimator.CrossFadeInFixedTime("AscendDescend", 0.1f, layerIndex); + } + modelAnimator.Update(0f); + } + } + + public override void OnExit() + { + if ((bool)rootMotionAccumulator) + { + rootMotionAccumulator.ExtractRootMotion(); + } + if ((bool)modelAnimator) + { + if (characterAnimParamAvailability.isMoving) + { + modelAnimator.SetBool(AnimationParameters.isMoving, value: false); + } + if (characterAnimParamAvailability.turnAngle) + { + modelAnimator.SetFloat(AnimationParameters.turnAngle, 0f); + } + } + base.OnExit(); + } + + public override void Update() + { + base.Update(); + if (!(Time.deltaTime <= 0f)) + { + UpdateEstimatedVelocity(); + useRootMotion = ((bool)base.characterBody && base.characterBody.rootMotionInMainState && base.isGrounded) || (bool)base.railMotor; + UpdateAnimationParameters(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void UpdateEstimatedVelocity() + { + Vector3 vector; + if (hasCharacterMotor) + { + vector = base.characterMotor.velocity; + } + else if (base.rigidbodyMotor != null && base.rigidbody != null) + { + vector = base.rigidbody.velocity; + } + else + { + Vector3 position = base.transform.position; + vector = (position - previousPosition) / Time.deltaTime; + previousPosition = position; + } + estimatedVelocity = (estimatedVelocity + vector + vector) * (1f / 3f); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (hasCharacterMotor) + { + float num = estimatedVelocity.y - lastYSpeed; + if (base.isGrounded && !wasGrounded && hasModelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Impact"); + if (layerIndex >= 0) + { + modelAnimator.SetLayerWeight(layerIndex, Mathf.Clamp01(Mathf.Max(0.3f, num / 5f, modelAnimator.GetLayerWeight(layerIndex)))); + modelAnimator.PlayInFixedTime("LightImpact", layerIndex, 0f); + } + } + wasGrounded = base.isGrounded; + lastYSpeed = estimatedVelocity.y; + } + if (!hasRootMotionAccumulator) + { + return; + } + Vector3 vector = rootMotionAccumulator.ExtractRootMotion(); + if (useRootMotion && vector != Vector3.zero && base.isAuthority) + { + if ((bool)base.characterMotor) + { + base.characterMotor.rootMotion += vector; + } + if ((bool)base.railMotor) + { + base.railMotor.rootMotion += vector; + } + } + } + + protected virtual void UpdateAnimationParameters() + { + if (hasRailMotor || !hasModelAnimator) + { + return; + } + float deltaTime = GetDeltaTime(); + Vector3 vector = (base.inputBank ? base.inputBank.moveVector : Vector3.zero); + bool value = vector != Vector3.zero && base.characterBody.moveSpeed > Mathf.Epsilon; + animatorWalkParamCalculator.Update(vector, base.characterDirection ? base.characterDirection.animatorForward : base.transform.forward, in smoothingParameters, deltaTime); + if (useRootMotion) + { + if (characterAnimParamAvailability.mainRootPlaybackRate) + { + float num = 1f; + if ((bool)base.modelLocator && (bool)base.modelLocator.modelTransform) + { + num = base.modelLocator.modelTransform.localScale.x; + } + float value2 = base.characterBody.moveSpeed / (base.characterBody.mainRootSpeed * num); + modelAnimator.SetFloat(AnimationParameters.mainRootPlaybackRate, value2); + } + } + else if (characterAnimParamAvailability.walkSpeed) + { + modelAnimator.SetFloat(AnimationParameters.walkSpeed, base.characterBody.moveSpeed); + } + if (characterAnimParamAvailability.isGrounded) + { + modelAnimator.SetBool(AnimationParameters.isGrounded, base.isGrounded); + } + if (characterAnimParamAvailability.isMoving) + { + modelAnimator.SetBool(AnimationParameters.isMoving, value); + } + if (characterAnimParamAvailability.turnAngle) + { + modelAnimator.SetFloat(AnimationParameters.turnAngle, animatorWalkParamCalculator.remainingTurnAngle, smoothingParameters.turnAngleSmoothDamp, deltaTime); + } + if (characterAnimParamAvailability.isSprinting) + { + modelAnimator.SetBool(AnimationParameters.isSprinting, base.characterBody.isSprinting); + } + if (characterAnimParamAvailability.forwardSpeed) + { + modelAnimator.SetFloat(AnimationParameters.forwardSpeed, animatorWalkParamCalculator.animatorWalkSpeed.x, smoothingParameters.forwardSpeedSmoothDamp, Time.deltaTime); + } + if (characterAnimParamAvailability.rightSpeed) + { + modelAnimator.SetFloat(AnimationParameters.rightSpeed, animatorWalkParamCalculator.animatorWalkSpeed.y, smoothingParameters.rightSpeedSmoothDamp, Time.deltaTime); + } + if (characterAnimParamAvailability.upSpeed) + { + modelAnimator.SetFloat(AnimationParameters.upSpeed, estimatedVelocity.y, 0.1f, Time.deltaTime); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BaseMelee.cs b/ilspy_dump/ror2_csproj/EntityStates/BaseMelee.cs new file mode 100644 index 0000000..c4a24b7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BaseMelee.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +namespace EntityStates; + +public class BaseMelee : BaseState +{ + protected RootMotionAccumulator rootMotionAccumulator; + + public RootMotionAccumulator InitMeleeRootMotion() + { + rootMotionAccumulator = GetModelRootMotionAccumulator(); + if ((bool)rootMotionAccumulator) + { + rootMotionAccumulator.ExtractRootMotion(); + } + if ((bool)base.characterDirection) + { + base.characterDirection.forward = base.inputBank.aimDirection; + } + if ((bool)base.characterMotor) + { + base.characterMotor.moveDirection = Vector3.zero; + } + return rootMotionAccumulator; + } + + public void UpdateMeleeRootMotion(float scale) + { + if ((bool)rootMotionAccumulator) + { + Vector3 vector = rootMotionAccumulator.ExtractRootMotion(); + if ((bool)base.characterMotor) + { + base.characterMotor.rootMotion = vector * scale; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BaseSkillState.cs b/ilspy_dump/ror2_csproj/EntityStates/BaseSkillState.cs new file mode 100644 index 0000000..c32b8e4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BaseSkillState.cs @@ -0,0 +1,26 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates; + +public class BaseSkillState : BaseState, ISkillState +{ + public GenericSkill activatorSkillSlot { get; set; } + + public override void OnSerialize(NetworkWriter writer) + { + base.OnSerialize(writer); + this.Serialize(base.skillLocator, writer); + } + + public override void OnDeserialize(NetworkReader reader) + { + base.OnDeserialize(reader); + this.Deserialize(base.skillLocator, reader); + } + + public bool IsKeyDownAuthority() + { + return this.IsKeyDownAuthority(base.skillLocator, base.inputBank); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BaseState.cs b/ilspy_dump/ror2_csproj/EntityStates/BaseState.cs new file mode 100644 index 0000000..8572a6f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BaseState.cs @@ -0,0 +1,290 @@ +using System; +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class BaseState : EntityState +{ + protected struct HitStopCachedState + { + public Vector3 characterVelocity; + + public string playbackName; + + public float playbackRate; + } + + protected float attackSpeedStat = 1f; + + protected float damageStat; + + protected float critStat; + + protected float moveSpeedStat; + + private const float defaultAimDuration = 2f; + + protected bool isGrounded + { + get + { + if ((bool)base.characterMotor) + { + return base.characterMotor.isGrounded; + } + return false; + } + } + + public override void Reset() + { + base.Reset(); + attackSpeedStat = 1f; + damageStat = 0f; + critStat = 0f; + moveSpeedStat = 0f; + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody) + { + attackSpeedStat = base.characterBody.attackSpeed; + damageStat = base.characterBody.damage; + critStat = base.characterBody.crit; + moveSpeedStat = base.characterBody.moveSpeed; + } + } + + protected Ray GetAimRay() + { + if ((bool)base.inputBank) + { + return new Ray(base.inputBank.aimOrigin, base.inputBank.aimDirection); + } + return new Ray(base.transform.position, base.transform.forward); + } + + protected void AddRecoil(float verticalMin, float verticalMax, float horizontalMin, float horizontalMax) + { + base.cameraTargetParams.AddRecoil(verticalMin, verticalMax, horizontalMin, horizontalMax); + } + + public OverlapAttack InitMeleeOverlap(float damageCoefficient, GameObject hitEffectPrefab, Transform modelTransform, string hitboxGroupName) + { + OverlapAttack overlapAttack = new OverlapAttack(); + overlapAttack.attacker = base.gameObject; + overlapAttack.inflictor = base.gameObject; + overlapAttack.teamIndex = TeamComponent.GetObjectTeam(overlapAttack.attacker); + overlapAttack.damage = damageCoefficient * damageStat; + overlapAttack.hitEffectPrefab = hitEffectPrefab; + overlapAttack.isCrit = RollCrit(); + if ((bool)modelTransform) + { + overlapAttack.hitBoxGroup = Array.Find(modelTransform.GetComponents(), (HitBoxGroup element) => element.groupName == hitboxGroupName); + } + return overlapAttack; + } + + public bool FireMeleeOverlap(OverlapAttack attack, Animator animator, string mecanimHitboxActiveParameter, float forceMagnitude, bool calculateForceVector = true) + { + bool result = false; + if ((bool)animator && animator.GetFloat(mecanimHitboxActiveParameter) > 0.1f) + { + if (calculateForceVector) + { + attack.forceVector = base.transform.forward * forceMagnitude; + } + result = attack.Fire(); + } + return result; + } + + public bool FireMeleeOverlap(OverlapAttack attack, Animator animator, int mecanimHitboxActiveParameterHash, float forceMagnitude, bool calculateForceVector = true) + { + bool result = false; + if ((bool)animator && animator.GetFloat(mecanimHitboxActiveParameterHash) > 0.1f) + { + if (calculateForceVector) + { + attack.forceVector = base.transform.forward * forceMagnitude; + } + result = attack.Fire(); + } + return result; + } + + public void SmallHop(CharacterMotor characterMotor, float smallHopVelocity) + { + if ((bool)characterMotor) + { + characterMotor.Motor.ForceUnground(); + characterMotor.velocity = new Vector3(characterMotor.velocity.x, Mathf.Max(characterMotor.velocity.y, smallHopVelocity), characterMotor.velocity.z); + } + } + + protected HitStopCachedState CreateHitStopCachedState(CharacterMotor characterMotor, Animator animator, string playbackRateAnimationParameter) + { + HitStopCachedState result = default(HitStopCachedState); + result.characterVelocity = new Vector3(characterMotor.velocity.x, Mathf.Max(0f, characterMotor.velocity.y), characterMotor.velocity.z); + result.playbackName = playbackRateAnimationParameter; + result.playbackRate = animator.GetFloat(result.playbackName); + return result; + } + + protected void ConsumeHitStopCachedState(HitStopCachedState hitStopCachedState, CharacterMotor characterMotor, Animator animator) + { + characterMotor.velocity = hitStopCachedState.characterVelocity; + animator.SetFloat(hitStopCachedState.playbackName, hitStopCachedState.playbackRate); + } + + protected void StartAimMode(float duration = 2f, bool snap = false) + { + StartAimMode(GetAimRay(), duration, snap); + } + + protected void StartAimMode(Ray aimRay, float duration = 2f, bool snap = false) + { + if ((bool)base.characterDirection && aimRay.direction != Vector3.zero) + { + if (snap) + { + base.characterDirection.forward = aimRay.direction; + } + else + { + base.characterDirection.moveVector = aimRay.direction; + } + } + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(duration); + } + if (!base.modelLocator) + { + return; + } + Transform modelTransform = base.modelLocator.modelTransform; + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component && snap) + { + component.AimImmediate(); + } + } + } + + protected bool RollCrit() + { + if ((bool)base.characterBody && (bool)base.characterBody.master) + { + return Util.CheckRoll(critStat, base.characterBody.master); + } + return false; + } + + protected Transform FindModelChild(string childName) + { + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + return modelChildLocator.FindChild(childName); + } + return null; + } + + protected T FindModelChildComponent(string childName) + { + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + return modelChildLocator.FindChildComponent(childName); + } + return default(T); + } + + protected GameObject FindModelChildGameObject(string childName) + { + ChildLocator modelChildLocator = GetModelChildLocator(); + if ((bool)modelChildLocator) + { + return modelChildLocator.FindChildGameObject(childName); + } + return null; + } + + public TeamIndex GetTeam() + { + return TeamComponent.GetObjectTeam(base.gameObject); + } + + public bool HasBuff(BuffIndex buffType) + { + if ((bool)base.characterBody) + { + return base.characterBody.HasBuff(buffType); + } + return false; + } + + public bool HasBuff(BuffDef buffType) + { + if ((bool)base.characterBody) + { + return base.characterBody.HasBuff(buffType); + } + return false; + } + + public int GetBuffCount(BuffIndex buffType) + { + if (!base.characterBody) + { + return 0; + } + return base.characterBody.GetBuffCount(buffType); + } + + public int GetBuffCount(BuffDef buffType) + { + if (!base.characterBody) + { + return 0; + } + return base.characterBody.GetBuffCount(buffType); + } + + protected void AttemptToStartSprint() + { + if ((bool)base.inputBank) + { + base.inputBank.sprint.down = true; + } + } + + protected HitBoxGroup FindHitBoxGroup(string groupName) + { + Transform modelTransform = GetModelTransform(); + if (!modelTransform) + { + return null; + } + HitBoxGroup result = null; + List gameObjectComponents = GetComponentsCache.GetGameObjectComponents(modelTransform.gameObject); + int i = 0; + for (int count = gameObjectComponents.Count; i < count; i++) + { + if (gameObjectComponents[i].groupName == groupName) + { + result = gameObjectComponents[i]; + break; + } + } + GetComponentsCache.ReturnBuffer(gameObjectComponents); + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BasicMeleeAttack.cs b/ilspy_dump/ror2_csproj/EntityStates/BasicMeleeAttack.cs new file mode 100644 index 0000000..3035cb1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BasicMeleeAttack.cs @@ -0,0 +1,362 @@ +using System.Collections.Generic; +using RoR2; +using RoR2.Audio; +using UnityEngine; + +namespace EntityStates; + +public class BasicMeleeAttack : BaseState +{ + [SerializeField] + public float baseDuration; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public string hitBoxGroupName; + + [SerializeField] + public GameObject hitEffectPrefab; + + [SerializeField] + public float procCoefficient; + + [SerializeField] + public float pushAwayForce; + + [SerializeField] + public Vector3 forceVector; + + [SerializeField] + public float hitPauseDuration; + + [SerializeField] + public GameObject swingEffectPrefab; + + [SerializeField] + public string swingEffectMuzzleString; + + [SerializeField] + public string mecanimHitboxActiveParameter; + + [SerializeField] + public float shorthopVelocityFromHit; + + [SerializeField] + public string beginStateSoundString; + + [SerializeField] + public string beginSwingSoundString; + + [SerializeField] + public NetworkSoundEventDef impactSound; + + [SerializeField] + public bool forceForwardVelocity; + + [SerializeField] + public AnimationCurve forwardVelocityCurve; + + [SerializeField] + public bool scaleHitPauseDurationAndVelocityWithAttackSpeed; + + [SerializeField] + public bool ignoreAttackSpeed; + + protected float duration; + + protected HitBoxGroup hitBoxGroup; + + protected Animator animator; + + private OverlapAttack overlapAttack; + + protected bool authorityHitThisFixedUpdate; + + protected float hitPauseTimer; + + protected Vector3 storedHitPauseVelocity; + + private Run.FixedTimeStamp meleeAttackStartTime = Run.FixedTimeStamp.positiveInfinity; + + private GameObject swingEffectInstance; + + private int meleeAttackTicks; + + protected List hitResults = new List(); + + private bool forceFire; + + protected EffectManagerHelper _emh_swingEffectInstance; + + protected bool authorityInHitPause => hitPauseTimer > 0f; + + private bool meleeAttackHasBegun => meleeAttackStartTime.hasPassed; + + protected bool authorityHasFiredAtAll => meleeAttackTicks > 0; + + protected bool isCritAuthority { get; private set; } + + protected virtual bool allowExitFire => true; + + public virtual string GetHitBoxGroupName() + { + return hitBoxGroupName; + } + + public override void Reset() + { + base.Reset(); + duration = 0f; + hitBoxGroup = null; + animator = null; + if (overlapAttack != null) + { + overlapAttack.Reset(); + } + authorityHitThisFixedUpdate = false; + hitPauseTimer = 0f; + storedHitPauseVelocity = Vector3.zero; + meleeAttackStartTime = Run.FixedTimeStamp.positiveInfinity; + swingEffectInstance = null; + meleeAttackTicks = 0; + forceFire = false; + _emh_swingEffectInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = CalcDuration(); + if (duration <= Time.fixedDeltaTime * 2f) + { + forceFire = true; + } + StartAimMode(); + Util.PlaySound(beginStateSoundString, base.gameObject); + animator = GetModelAnimator(); + if (base.isAuthority) + { + isCritAuthority = RollCrit(); + hitBoxGroup = FindHitBoxGroup(GetHitBoxGroupName()); + if ((bool)hitBoxGroup) + { + overlapAttack = new OverlapAttack + { + attacker = base.gameObject, + damage = damageCoefficient * damageStat, + damageColorIndex = DamageColorIndex.Default, + damageType = DamageType.Generic, + forceVector = forceVector, + hitBoxGroup = hitBoxGroup, + hitEffectPrefab = hitEffectPrefab, + impactSound = (impactSound?.index ?? NetworkSoundEventIndex.Invalid), + inflictor = base.gameObject, + isCrit = isCritAuthority, + procChainMask = default(ProcChainMask), + pushAwayForce = pushAwayForce, + procCoefficient = procCoefficient, + teamIndex = GetTeam() + }; + } + } + PlayAnimation(); + } + + protected virtual float CalcDuration() + { + if (ignoreAttackSpeed) + { + return baseDuration; + } + return baseDuration / attackSpeedStat; + } + + protected virtual void AuthorityModifyOverlapAttack(OverlapAttack overlapAttack) + { + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (string.IsNullOrEmpty(mecanimHitboxActiveParameter)) + { + BeginMeleeAttackEffect(); + } + else if (animator.GetFloat(mecanimHitboxActiveParameter) > 0.5f) + { + BeginMeleeAttackEffect(); + } + if (base.isAuthority) + { + AuthorityFixedUpdate(); + } + } + + protected void AuthorityTriggerHitPause() + { + if ((bool)base.characterMotor) + { + storedHitPauseVelocity += base.characterMotor.velocity; + base.characterMotor.velocity = Vector3.zero; + } + if ((bool)animator) + { + animator.speed = 0f; + } + if ((bool)swingEffectInstance) + { + ScaleParticleSystemDuration component = swingEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = 20f; + } + } + hitPauseTimer = (scaleHitPauseDurationAndVelocityWithAttackSpeed ? (hitPauseDuration / attackSpeedStat) : hitPauseDuration); + } + + protected virtual void BeginMeleeAttackEffect() + { + if (meleeAttackStartTime != Run.FixedTimeStamp.positiveInfinity) + { + return; + } + meleeAttackStartTime = Run.FixedTimeStamp.now; + Util.PlaySound(beginSwingSoundString, base.gameObject); + if (!swingEffectPrefab) + { + return; + } + Transform transform = FindModelChild(swingEffectMuzzleString); + if ((bool)transform) + { + if (!EffectManager.ShouldUsePooledEffect(swingEffectPrefab)) + { + swingEffectInstance = Object.Instantiate(swingEffectPrefab, transform); + } + else + { + _emh_swingEffectInstance = EffectManager.GetAndActivatePooledEffect(swingEffectPrefab, transform, inResetLocal: true); + swingEffectInstance = _emh_swingEffectInstance.gameObject; + } + ScaleParticleSystemDuration component = swingEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = component.initialDuration; + } + } + } + + protected virtual void AuthorityExitHitPause() + { + hitPauseTimer = 0f; + storedHitPauseVelocity.y = Mathf.Max(storedHitPauseVelocity.y, scaleHitPauseDurationAndVelocityWithAttackSpeed ? (shorthopVelocityFromHit / Mathf.Sqrt(attackSpeedStat)) : shorthopVelocityFromHit); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = storedHitPauseVelocity; + } + storedHitPauseVelocity = Vector3.zero; + if ((bool)animator) + { + animator.speed = 1f; + } + if ((bool)swingEffectInstance) + { + ScaleParticleSystemDuration component = swingEffectInstance.GetComponent(); + if ((bool)component) + { + component.newDuration = component.initialDuration; + } + } + } + + protected virtual void PlayAnimation() + { + } + + protected virtual void OnMeleeHitAuthority() + { + } + + private void AuthorityFireAttack() + { + AuthorityModifyOverlapAttack(overlapAttack); + hitResults.Clear(); + authorityHitThisFixedUpdate = overlapAttack.Fire(hitResults); + meleeAttackTicks++; + if (authorityHitThisFixedUpdate) + { + AuthorityTriggerHitPause(); + OnMeleeHitAuthority(); + } + } + + protected virtual void AuthorityFixedUpdate() + { + if (authorityInHitPause) + { + hitPauseTimer -= GetDeltaTime(); + if ((bool)base.characterMotor) + { + base.characterMotor.velocity = Vector3.zero; + } + base.fixedAge -= GetDeltaTime(); + if (!authorityInHitPause) + { + AuthorityExitHitPause(); + } + } + else if (forceForwardVelocity && (bool)base.characterMotor && (bool)base.characterDirection) + { + Vector3 vector = base.characterDirection.forward * forwardVelocityCurve.Evaluate(base.fixedAge / duration); + _ = base.characterMotor.velocity; + base.characterMotor.AddDisplacement(new Vector3(vector.x, 0f, vector.z)); + } + authorityHitThisFixedUpdate = false; + if (overlapAttack != null && (string.IsNullOrEmpty(mecanimHitboxActiveParameter) || animator.GetFloat(mecanimHitboxActiveParameter) > 0.5f || forceFire)) + { + AuthorityFireAttack(); + } + if (duration <= base.fixedAge) + { + AuthorityOnFinish(); + } + } + + public override void OnExit() + { + if (base.isAuthority) + { + if (!outer.destroying && !authorityHasFiredAtAll && allowExitFire) + { + BeginMeleeAttackEffect(); + AuthorityFireAttack(); + } + if (authorityInHitPause) + { + AuthorityExitHitPause(); + } + } + if (_emh_swingEffectInstance != null && _emh_swingEffectInstance.OwningPool != null) + { + _emh_swingEffectInstance.OwningPool.ReturnObject(_emh_swingEffectInstance); + } + else if ((bool)swingEffectInstance) + { + EntityState.Destroy(swingEffectInstance); + } + swingEffectInstance = null; + _emh_swingEffectInstance = null; + if ((bool)animator) + { + animator.speed = 1f; + } + base.OnExit(); + } + + protected virtual void AuthorityOnFinish() + { + outer.SetNextStateToMain(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/BigCharacterMain.cs b/ilspy_dump/ror2_csproj/EntityStates/BigCharacterMain.cs new file mode 100644 index 0000000..8d94294 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/BigCharacterMain.cs @@ -0,0 +1,16 @@ +namespace EntityStates; + +public class BigCharacterMain : GenericCharacterMain +{ + public override void ProcessJump() + { + if (base.characterMotor.jumpCount > base.characterBody.baseJumpCount) + { + base.ProcessJump(); + } + else if (jumpInputReceived && base.characterMotor.isGrounded) + { + outer.SetNextState(new AnimatedJump()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/CloakTest.cs b/ilspy_dump/ror2_csproj/EntityStates/CloakTest.cs new file mode 100644 index 0000000..5831048 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/CloakTest.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates; + +public class CloakTest : BaseState +{ + private float duration = 3f; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.Cloak); + base.characterBody.AddBuff(RoR2Content.Buffs.CloakSpeed); + } + } + + public override void OnExit() + { + if ((bool)base.characterBody && NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.Cloak); + base.characterBody.RemoveBuff(RoR2Content.Buffs.CloakSpeed); + } + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/EmotePoint.cs b/ilspy_dump/ror2_csproj/EntityStates/EmotePoint.cs new file mode 100644 index 0000000..b4033ee --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/EmotePoint.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace EntityStates; + +public class EmotePoint : BaseState +{ + public static float duration = 0.5f; + + private static int EmotePointStateHash = Animator.StringToHash("EmotePoint"); + + private static int EmotePointplaybackRateParamHash = Animator.StringToHash("EmotePoint.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Gesture"); + modelAnimator.SetFloat(EmotePointplaybackRateParamHash, 1f); + modelAnimator.PlayInFixedTime(EmotePointStateHash, layerIndex, 0f); + modelAnimator.Update(0f); + modelAnimator.SetFloat(EmotePointplaybackRateParamHash, attackSpeedStat); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/EntityState.cs b/ilspy_dump/ror2_csproj/EntityStates/EntityState.cs new file mode 100644 index 0000000..f413a1c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/EntityState.cs @@ -0,0 +1,422 @@ +using System; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates; + +public class EntityState +{ + public EntityStateMachine outer; + + protected float age { get; set; } + + protected float fixedAge { get; set; } + + protected GameObject gameObject => outer.gameObject; + + protected bool isLocalPlayer + { + get + { + if ((bool)outer.networker) + { + return outer.networker.isLocalPlayer; + } + return false; + } + } + + protected bool localPlayerAuthority + { + get + { + if ((bool)outer.networker) + { + return outer.networker.localPlayerAuthority; + } + return false; + } + } + + protected bool isAuthority => Util.HasEffectiveAuthority(outer.networkIdentity); + + protected Transform transform => outer.commonComponents.transform; + + protected CharacterBody characterBody => outer.commonComponents.characterBody; + + protected CharacterMotor characterMotor => outer.commonComponents.characterMotor; + + protected CharacterDirection characterDirection => outer.commonComponents.characterDirection; + + protected Rigidbody rigidbody => outer.commonComponents.rigidbody; + + protected RigidbodyMotor rigidbodyMotor => outer.commonComponents.rigidbodyMotor; + + protected RigidbodyDirection rigidbodyDirection => outer.commonComponents.rigidbodyDirection; + + protected RailMotor railMotor => outer.commonComponents.railMotor; + + protected ModelLocator modelLocator => outer.commonComponents.modelLocator; + + protected InputBankTest inputBank => outer.commonComponents.inputBank; + + protected TeamComponent teamComponent => outer.commonComponents.teamComponent; + + protected HealthComponent healthComponent => outer.commonComponents.healthComponent; + + protected SkillLocator skillLocator => outer.commonComponents.skillLocator; + + protected CharacterEmoteDefinitions characterEmoteDefinitions => outer.commonComponents.characterEmoteDefinitions; + + protected CameraTargetParams cameraTargetParams => outer.commonComponents.cameraTargetParams; + + protected SfxLocator sfxLocator => outer.commonComponents.sfxLocator; + + protected BodyAnimatorSmoothingParameters bodyAnimatorSmoothingParameters => outer.commonComponents.bodyAnimatorSmoothingParameters; + + protected ProjectileController projectileController => outer.commonComponents.projectileController; + + public void ClearEntityStateMachine() + { + outer = null; + } + + public EntityState() + { + EntityStateCatalog.InitializeStateFields(this); + } + + public virtual void OnEnter() + { + } + + public virtual void OnExit() + { + } + + public virtual void ModifyNextState(EntityState nextState) + { + } + + public virtual void Update() + { + age += Time.deltaTime; + } + + public virtual void FixedUpdate() + { + fixedAge += GetDeltaTime(); + } + + protected float GetDeltaTime() + { + return Time.fixedDeltaTime; + } + + public virtual void OnSerialize(NetworkWriter writer) + { + } + + public virtual void OnDeserialize(NetworkReader reader) + { + } + + public virtual InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } + + public virtual void Reset() + { + ClearEntityStateMachine(); + age = 0f; + fixedAge = 0f; + } + + public void SetAIUpdateFrequency(bool alwaysUpdate) + { + if ((bool)characterBody && (bool)characterBody.master) + { + characterBody.master.SetAIUpdateFrequency(alwaysUpdate); + } + } + + protected static void Destroy(UnityEngine.Object obj) + { + UnityEngine.Object.Destroy(obj); + } + + protected T GetComponent() where T : Component + { + return outer.GetComponent(); + } + + protected Component GetComponent(Type type) + { + return outer.GetComponent(type); + } + + protected Component GetComponent(string type) + { + return outer.GetComponent(type); + } + + protected Transform GetModelBaseTransform() + { + if (!modelLocator) + { + return null; + } + return modelLocator.modelBaseTransform; + } + + protected Transform GetModelTransform() + { + if (!modelLocator) + { + return null; + } + return modelLocator.modelTransform; + } + + protected AimAnimator GetAimAnimator() + { + if ((bool)modelLocator && (bool)modelLocator.modelTransform) + { + return modelLocator.modelTransform.GetComponent(); + } + return null; + } + + protected Animator GetModelAnimator() + { + if ((bool)modelLocator && (bool)modelLocator.modelTransform) + { + return modelLocator.modelTransform.GetComponent(); + } + return null; + } + + protected ChildLocator GetModelChildLocator() + { + if ((bool)modelLocator && (bool)modelLocator.modelTransform) + { + return modelLocator.modelTransform.GetComponent(); + } + return null; + } + + protected RootMotionAccumulator GetModelRootMotionAccumulator() + { + if ((bool)modelLocator && (bool)modelLocator.modelTransform) + { + return modelLocator.modelTransform.GetComponent(); + } + return null; + } + + protected void PlayAnimation(string layerName, string animationStateName, string playbackRateParam, float duration, float transition = 0f) + { + if (duration <= 0f) + { + Debug.LogWarningFormat("EntityState.PlayAnimation: Zero duration is not allowed. type={0}", GetType().Name); + return; + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayAnimationOnAnimator(modelAnimator, layerName, animationStateName, playbackRateParam, duration, transition); + } + } + + protected void PlayAnimation(string layerName, int animationStateHash, int playbackRateParamHash, float duration) + { + if (duration <= 0f) + { + Debug.LogWarningFormat("EntityState.PlayAnimation: Zero duration is not allowed. type={0}", GetType().Name); + return; + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex(layerName); + if (layerIndex >= 0) + { + PlayAnimationOnAnimator(modelAnimator, layerIndex, animationStateHash, playbackRateParamHash, duration); + } + } + } + + protected static void PlayAnimationOnAnimator(Animator modelAnimator, string layerName, string animationStateName, string playbackRateParam, float duration, float transition = 0f) + { + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + int layerIndex = modelAnimator.GetLayerIndex(layerName); + if (layerIndex >= 0) + { + if (!string.IsNullOrEmpty(playbackRateParam)) + { + modelAnimator.SetFloat(playbackRateParam, 1f); + } + if (transition > 0f) + { + modelAnimator.CrossFadeInFixedTime(animationStateName, transition, layerIndex); + } + else + { + modelAnimator.PlayInFixedTime(animationStateName, layerIndex, 0f); + } + modelAnimator.Update(0f); + float length = modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).length; + if (!string.IsNullOrEmpty(playbackRateParam)) + { + modelAnimator.SetFloat(playbackRateParam, length / duration); + } + } + } + + protected static void PlayAnimationOnAnimator(Animator modelAnimator, string layerName, int animationStateHash, int playbackRateParamHash, float duration) + { + int layerIndex = modelAnimator.GetLayerIndex(layerName); + if (layerIndex >= 0) + { + PlayAnimationOnAnimator(modelAnimator, layerIndex, animationStateHash, playbackRateParamHash, duration); + } + } + + protected static void PlayAnimationOnAnimator(Animator modelAnimator, int layerIndex, int animationStateHash, int playbackRateParamHash, float duration) + { + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + if (layerIndex >= 0) + { + modelAnimator.SetFloat(playbackRateParamHash, 1f); + modelAnimator.PlayInFixedTime(animationStateHash, layerIndex, 0f); + modelAnimator.Update(0f); + float length = modelAnimator.GetCurrentAnimatorStateInfo(layerIndex).length; + modelAnimator.SetFloat(playbackRateParamHash, length / duration); + } + } + + protected void PlayCrossfade(string layerName, string animationStateName, string playbackRateParam, float duration, float crossfadeDuration) + { + if (duration <= 0f) + { + Debug.LogWarningFormat("EntityState.PlayCrossfade: Zero duration is not allowed. type={0}", GetType().Name); + return; + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + int layerIndex = modelAnimator.GetLayerIndex(layerName); + modelAnimator.SetFloat(playbackRateParam, 1f); + modelAnimator.CrossFadeInFixedTime(animationStateName, crossfadeDuration, layerIndex); + modelAnimator.Update(0f); + float length = modelAnimator.GetNextAnimatorStateInfo(layerIndex).length; + modelAnimator.SetFloat(playbackRateParam, length / duration); + } + } + + protected void PlayCrossfade(string layerName, int animationStateNameHash, int playbackRateParamHash, float duration, float crossfadeDuration) + { + if (duration <= 0f) + { + Debug.LogWarningFormat("EntityState.PlayCrossfade: Zero duration is not allowed. type={0}", GetType().Name); + return; + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + int layerIndex = modelAnimator.GetLayerIndex(layerName); + modelAnimator.SetFloat(playbackRateParamHash, 1f); + modelAnimator.CrossFadeInFixedTime(animationStateNameHash, crossfadeDuration, layerIndex); + modelAnimator.Update(0f); + float length = modelAnimator.GetNextAnimatorStateInfo(layerIndex).length; + modelAnimator.SetFloat(playbackRateParamHash, length / duration); + } + } + + protected void PlayCrossfade(string layerName, string animationStateName, float crossfadeDuration) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + int layerIndex = modelAnimator.GetLayerIndex(layerName); + modelAnimator.CrossFadeInFixedTime(animationStateName, crossfadeDuration, layerIndex); + } + } + + protected void PlayCrossfade(string layerName, int animationStateHash, float crossfadeDuration) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + int layerIndex = modelAnimator.GetLayerIndex(layerName); + modelAnimator.CrossFadeInFixedTime(animationStateHash, crossfadeDuration, layerIndex); + } + } + + public virtual void PlayAnimation(string layerName, string animationStateName) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayAnimationOnAnimator(modelAnimator, layerName, animationStateName); + } + } + + public virtual void PlayAnimation(string layerName, int animationStateHash) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + PlayAnimationOnAnimator(modelAnimator, layerName, animationStateHash); + } + } + + public virtual void SetPingable(bool value) + { + if ((bool)outer && (bool)outer.networkIdentity) + { + outer.networkIdentity.isPingable = value; + } + } + + protected static void PlayAnimationOnAnimator(Animator modelAnimator, string layerName, string animationStateName) + { + int layerIndex = modelAnimator.GetLayerIndex(layerName); + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + modelAnimator.PlayInFixedTime(animationStateName, layerIndex, 0f); + } + + protected static void PlayAnimationOnAnimator(Animator modelAnimator, string layerName, int animationStateHash) + { + int layerIndex = modelAnimator.GetLayerIndex(layerName); + modelAnimator.speed = 1f; + modelAnimator.Update(0f); + modelAnimator.PlayInFixedTime(animationStateHash, layerIndex, 0f); + } + + protected void GetBodyAnimatorSmoothingParameters(out BodyAnimatorSmoothingParameters.SmoothingParameters smoothingParameters) + { + if ((bool)bodyAnimatorSmoothingParameters) + { + smoothingParameters = bodyAnimatorSmoothingParameters.smoothingParameters; + } + else + { + smoothingParameters = BodyAnimatorSmoothingParameters.defaultParameters; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/FireFlower2.cs b/ilspy_dump/ror2_csproj/EntityStates/FireFlower2.cs new file mode 100644 index 0000000..8103405 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/FireFlower2.cs @@ -0,0 +1,84 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates; + +public class FireFlower2 : BaseState +{ + public static GameObject projectilePrefab; + + public static float baseDuration; + + public static float damageCoefficient; + + public static float healthCostFraction; + + public static string enterSoundString; + + public static string muzzleName; + + public static GameObject muzzleFlashPrefab; + + private float duration; + + private static int FireFlowerStateHash = Animator.StringToHash("FireFlower"); + + private static int FireFlowerParamHash = Animator.StringToHash("FireFlower.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", FireFlowerStateHash, FireFlowerParamHash, duration); + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.crit = RollCrit(); + fireProjectileInfo.damage = damageCoefficient * damageStat; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.force = 0f; + fireProjectileInfo.owner = base.gameObject; + fireProjectileInfo.position = aimRay.origin; + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.projectilePrefab = projectilePrefab; + fireProjectileInfo.rotation = Quaternion.LookRotation(aimRay.direction); + fireProjectileInfo.useSpeedOverride = false; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + if (NetworkServer.active && (bool)base.healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = base.healthComponent.combinedHealth * healthCostFraction; + damageInfo.position = base.characterBody.corePosition; + damageInfo.force = Vector3.zero; + damageInfo.damageColorIndex = DamageColorIndex.Default; + damageInfo.crit = false; + damageInfo.attacker = null; + damageInfo.inflictor = null; + damageInfo.damageType = DamageType.NonLethal | DamageType.BypassArmor; + damageInfo.procCoefficient = 0f; + damageInfo.procChainMask = default(ProcChainMask); + base.healthComponent.TakeDamage(damageInfo); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/FlyState.cs b/ilspy_dump/ror2_csproj/EntityStates/FlyState.cs new file mode 100644 index 0000000..14932bf --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/FlyState.cs @@ -0,0 +1,130 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class FlyState : BaseState +{ + private Animator modelAnimator; + + private bool skill1InputReceived; + + private bool skill2InputReceived; + + private bool skill3InputReceived; + + private bool skill4InputReceived; + + private static int IdleStateHash = Animator.StringToHash("Idle"); + + private bool hasPivotPitchLayer; + + private bool hasPivotYawLayer; + + private bool hasPivotRollLayer; + + private static readonly int pivotPitchCycle = Animator.StringToHash("pivotPitchCycle"); + + private static readonly int pivotYawCycle = Animator.StringToHash("pivotYawCycle"); + + private static readonly int pivotRollCycle = Animator.StringToHash("pivotRollCycle"); + + private static readonly int flyRate = Animator.StringToHash("fly.rate"); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + PlayAnimation("Body", IdleStateHash); + if ((bool)modelAnimator) + { + hasPivotPitchLayer = modelAnimator.GetLayerIndex("PivotPitch") != -1; + hasPivotYawLayer = modelAnimator.GetLayerIndex("PivotYaw") != -1; + hasPivotRollLayer = modelAnimator.GetLayerIndex("PivotRoll") != -1; + } + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if ((bool)base.rigidbodyDirection) + { + Quaternion rotation = base.transform.rotation; + Quaternion quaternion = Util.QuaternionSafeLookRotation(base.rigidbodyDirection.aimDirection); + Quaternion quaternion2 = Quaternion.Inverse(rotation) * quaternion; + if ((bool)modelAnimator) + { + float deltaTime = GetDeltaTime(); + if (hasPivotPitchLayer) + { + modelAnimator.SetFloat(pivotPitchCycle, Mathf.Clamp01(Util.Remap(quaternion2.x * Mathf.Sign(quaternion2.w), -1f, 1f, 0f, 1f)), 1f, deltaTime); + } + if (hasPivotYawLayer) + { + modelAnimator.SetFloat(pivotYawCycle, Mathf.Clamp01(Util.Remap(quaternion2.y * Mathf.Sign(quaternion2.w), -1f, 1f, 0f, 1f)), 1f, deltaTime); + } + if (hasPivotRollLayer) + { + modelAnimator.SetFloat(pivotRollCycle, Mathf.Clamp01(Util.Remap(quaternion2.z * Mathf.Sign(quaternion2.w), -1f, 1f, 0f, 1f)), 1f, deltaTime); + } + } + } + PerformInputs(); + } + + protected virtual bool CanExecuteSkill(GenericSkill skillSlot) + { + return true; + } + + protected virtual void PerformInputs() + { + if (!base.isAuthority) + { + return; + } + if ((bool)base.inputBank) + { + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = base.inputBank.moveVector * base.characterBody.moveSpeed; + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(flyRate, Vector3.Magnitude(base.rigidbodyMotor.rigid.velocity)); + } + } + if ((bool)base.rigidbodyDirection) + { + base.rigidbodyDirection.aimDirection = GetAimRay().direction; + } + skill1InputReceived = base.inputBank.skill1.down; + skill2InputReceived = base.inputBank.skill2.down; + skill3InputReceived = base.inputBank.skill3.down; + skill4InputReceived = base.inputBank.skill4.down; + } + if ((bool)base.skillLocator) + { + if (skill1InputReceived && (bool)base.skillLocator.primary && CanExecuteSkill(base.skillLocator.primary)) + { + base.skillLocator.primary.ExecuteIfReady(); + } + if (skill2InputReceived && (bool)base.skillLocator.secondary && CanExecuteSkill(base.skillLocator.secondary)) + { + base.skillLocator.secondary.ExecuteIfReady(); + } + if (skill3InputReceived && (bool)base.skillLocator.utility && CanExecuteSkill(base.skillLocator.utility)) + { + base.skillLocator.utility.ExecuteIfReady(); + } + if (skill4InputReceived && (bool)base.skillLocator.special && CanExecuteSkill(base.skillLocator.special)) + { + base.skillLocator.special.ExecuteIfReady(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/FrozenState.cs b/ilspy_dump/ror2_csproj/EntityStates/FrozenState.cs new file mode 100644 index 0000000..f353542 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/FrozenState.cs @@ -0,0 +1,98 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class FrozenState : BaseState +{ + private float duration; + + private Animator modelAnimator; + + private TemporaryOverlayInstance temporaryOverlay; + + public float freezeDuration = 0.35f; + + public static GameObject frozenEffectPrefab; + + public static GameObject executeEffectPrefab; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + CharacterModel component = modelTransform.GetComponent(); + if ((bool)component) + { + temporaryOverlay = TemporaryOverlayManager.AddOverlay(base.gameObject); + temporaryOverlay.duration = freezeDuration; + temporaryOverlay.originalMaterial = LegacyResourcesAPI.Load("Materials/matIsFrozen"); + temporaryOverlay.AddToCharacterModel(component); + } + } + modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.enabled = false; + duration = freezeDuration; + EffectManager.SpawnEffect(frozenEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition, + scale = (base.characterBody ? base.characterBody.radius : 1f) + }, transmit: false); + } + if ((bool)base.rigidbody && !base.rigidbody.isKinematic) + { + base.rigidbody.velocity = Vector3.zero; + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + } + base.healthComponent.isInFrozenState = true; + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + } + + public override void OnExit() + { + if ((bool)modelAnimator) + { + modelAnimator.enabled = true; + } + if (temporaryOverlay != null) + { + temporaryOverlay.Destroy(); + temporaryOverlay = null; + } + EffectManager.SpawnEffect(frozenEffectPrefab, new EffectData + { + origin = base.characterBody.corePosition, + scale = (base.characterBody ? base.characterBody.radius : 1f) + }, transmit: false); + base.healthComponent.isInFrozenState = false; + base.OnExit(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.isAuthority && base.fixedAge >= duration) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Frozen; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericBulletBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericBulletBaseState.cs new file mode 100644 index 0000000..8fc59af --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericBulletBaseState.cs @@ -0,0 +1,172 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public abstract class GenericBulletBaseState : BaseState +{ + [SerializeField] + public float baseDuration = 0.1f; + + [SerializeField] + public int bulletCount = 1; + + [SerializeField] + public float maxDistance = 50f; + + [SerializeField] + public float bulletRadius; + + [SerializeField] + public bool useSmartCollision; + + [SerializeField] + public float damageCoefficient = 0.1f; + + [SerializeField] + public float procCoefficient = 1f; + + [SerializeField] + public float force = 100f; + + [SerializeField] + public float minSpread; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public float spreadPitchScale = 0.5f; + + [SerializeField] + public float spreadYawScale = 1f; + + [SerializeField] + public float spreadBloomValue = 0.2f; + + [SerializeField] + public float recoilAmplitudeY; + + [SerializeField] + public float recoilAmplitudeX; + + [SerializeField] + public string muzzleName; + + [SerializeField] + public string fireSoundString; + + [SerializeField] + public GameObject muzzleFlashPrefab; + + [SerializeField] + public GameObject tracerEffectPrefab; + + [SerializeField] + public GameObject hitEffectPrefab; + + protected float duration; + + protected Transform muzzleTransform; + + protected BulletAttack GenerateBulletAttack(Ray aimRay) + { + float num = 0f; + if ((bool)base.characterBody) + { + num = base.characterBody.spreadBloomAngle; + } + return new BulletAttack + { + aimVector = aimRay.direction, + origin = aimRay.origin, + owner = base.gameObject, + weapon = null, + bulletCount = (uint)bulletCount, + damage = damageStat * damageCoefficient, + damageColorIndex = DamageColorIndex.Default, + damageType = DamageType.Generic, + falloffModel = BulletAttack.FalloffModel.Buckshot, + force = force, + HitEffectNormal = false, + procChainMask = default(ProcChainMask), + procCoefficient = procCoefficient, + maxDistance = maxDistance, + radius = bulletRadius, + isCrit = RollCrit(), + muzzleName = muzzleName, + minSpread = minSpread, + maxSpread = maxSpread + num, + hitEffectPrefab = hitEffectPrefab, + smartCollision = useSmartCollision, + sniper = false, + spreadPitchScale = spreadPitchScale, + spreadYawScale = spreadYawScale, + tracerEffectPrefab = tracerEffectPrefab + }; + } + + protected virtual void PlayFireAnimation() + { + } + + protected virtual void DoFireEffects() + { + Util.PlaySound(fireSoundString, base.gameObject); + if ((bool)muzzleTransform) + { + EffectManager.SimpleMuzzleFlash(muzzleFlashPrefab, base.gameObject, muzzleName, transmit: false); + } + } + + protected virtual void ModifyBullet(BulletAttack bulletAttack) + { + } + + protected virtual void FireBullet(Ray aimRay) + { + StartAimMode(aimRay, 3f); + DoFireEffects(); + PlayFireAnimation(); + AddRecoil(-1f * recoilAmplitudeY, -1.5f * recoilAmplitudeY, -1f * recoilAmplitudeX, 1f * recoilAmplitudeX); + if (base.isAuthority) + { + BulletAttack bulletAttack = GenerateBulletAttack(aimRay); + ModifyBullet(bulletAttack); + bulletAttack.Fire(); + OnFireBulletAuthority(aimRay); + } + } + + protected virtual void OnFireBulletAuthority(Ray aimRay) + { + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + muzzleTransform = FindModelChild(muzzleName); + FireBullet(GetAimRay()); + base.characterBody.AddSpreadBloom(spreadBloomValue); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(InstantiateNextState()); + } + } + + protected virtual EntityState InstantiateNextState() + { + return EntityStateCatalog.InstantiateState(ref outer.mainStateType); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Skill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterDeath.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterDeath.cs new file mode 100644 index 0000000..f4d5ebc --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterDeath.cs @@ -0,0 +1,201 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates; + +public class GenericCharacterDeath : BaseState +{ + private static readonly float bodyPreservationDuration = 1f; + + private static readonly float hardCutoffDuration = 10f; + + private static readonly float maxFallDuration = 4f; + + private static readonly float minTimeToKeepBodyForNetworkMessages = 0.5f; + + public static GameObject voidDeathEffect; + + private float restStopwatch; + + private float fallingStopwatch; + + private bool bodyMarkedForDestructionServer; + + private CameraTargetParams.AimRequest aimRequest; + + protected Transform cachedModelTransform { get; private set; } + + protected bool isBrittle { get; private set; } + + protected bool isVoidDeath { get; private set; } + + protected bool isPlayerDeath { get; private set; } + + protected virtual bool shouldAutoDestroy => true; + + protected virtual float GetDeathAnimationCrossFadeDuration() + { + return 0.1f; + } + + public override void OnEnter() + { + base.OnEnter(); + bodyMarkedForDestructionServer = false; + cachedModelTransform = (base.modelLocator ? base.modelLocator.modelTransform : null); + isBrittle = (bool)base.characterBody && base.characterBody.isGlass; + isVoidDeath = (bool)base.healthComponent && (ulong)(base.healthComponent.killingDamageType & DamageType.VoidDeath) != 0; + isPlayerDeath = (bool)base.characterBody.master && base.characterBody.master.GetComponent() != null; + if (isVoidDeath) + { + if ((bool)base.characterBody && base.isAuthority) + { + EffectManager.SpawnEffect(voidDeathEffect, new EffectData + { + origin = base.characterBody.corePosition, + scale = base.characterBody.bestFitRadius + }, transmit: true); + } + if ((bool)cachedModelTransform) + { + EntityState.Destroy(cachedModelTransform.gameObject); + cachedModelTransform = null; + } + } + if (isPlayerDeath && (bool)base.characterBody) + { + Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/TemporaryVisualEffects/PlayerDeathEffect"), base.characterBody.corePosition, Quaternion.identity).GetComponent().targetCharacter = base.characterBody.gameObject; + } + if ((bool)cachedModelTransform) + { + if (isBrittle) + { + TemporaryOverlayInstance temporaryOverlayInstance = TemporaryOverlayManager.AddOverlay(cachedModelTransform.gameObject); + temporaryOverlayInstance.duration = 0.5f; + temporaryOverlayInstance.destroyObjectOnEnd = true; + temporaryOverlayInstance.originalMaterial = LegacyResourcesAPI.Load("Materials/matShatteredGlass"); + temporaryOverlayInstance.destroyEffectPrefab = LegacyResourcesAPI.Load("Prefabs/Effects/BrittleDeath"); + temporaryOverlayInstance.destroyEffectChildString = "Chest"; + temporaryOverlayInstance.inspectorCharacterModel = cachedModelTransform.gameObject.GetComponent(); + temporaryOverlayInstance.alphaCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + temporaryOverlayInstance.animateShaderAlpha = true; + temporaryOverlayInstance.transmit = false; + } + if ((bool)base.cameraTargetParams) + { + ChildLocator component = cachedModelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild("Chest"); + if ((bool)transform) + { + base.cameraTargetParams.cameraPivotTransform = transform; + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + base.cameraTargetParams.dontRaycastToPivot = true; + } + } + } + } + if (!isVoidDeath) + { + PlayDeathSound(); + PlayDeathAnimation(); + CreateDeathEffects(); + } + } + + protected virtual void PlayDeathSound() + { + if ((bool)base.sfxLocator && base.sfxLocator.deathSound != "") + { + Util.PlaySound(base.sfxLocator.deathSound, base.gameObject); + } + } + + protected virtual void PlayDeathAnimation(float crossfadeDuration = 0.1f) + { + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + modelAnimator.CrossFadeInFixedTime("Death", crossfadeDuration); + } + } + + protected virtual void CreateDeathEffects() + { + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!NetworkServer.active) + { + return; + } + bool flag = false; + bool flag2 = true; + if ((bool)base.characterMotor) + { + flag = base.characterMotor.isGrounded; + flag2 = base.characterMotor.atRest; + } + else if ((bool)base.rigidbodyMotor) + { + flag = false; + flag2 = false; + } + float deltaTime = GetDeltaTime(); + fallingStopwatch = (flag ? 0f : (fallingStopwatch + deltaTime)); + restStopwatch = ((!flag2) ? 0f : (restStopwatch + deltaTime)); + if (!(base.fixedAge >= minTimeToKeepBodyForNetworkMessages)) + { + return; + } + if (!bodyMarkedForDestructionServer) + { + if ((restStopwatch >= bodyPreservationDuration || fallingStopwatch >= maxFallDuration || base.fixedAge > hardCutoffDuration) && shouldAutoDestroy) + { + DestroyBodyAsapServer(); + } + } + else + { + OnPreDestroyBodyServer(); + EntityState.Destroy(base.gameObject); + } + } + + protected void DestroyBodyAsapServer() + { + bodyMarkedForDestructionServer = true; + } + + protected virtual void OnPreDestroyBodyServer() + { + } + + protected void DestroyModel() + { + if ((bool)cachedModelTransform) + { + EntityState.Destroy(cachedModelTransform.gameObject); + cachedModelTransform = null; + } + } + + public override void OnExit() + { + aimRequest?.Dispose(); + if (shouldAutoDestroy && fallingStopwatch >= maxFallDuration) + { + DestroyModel(); + } + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterMain.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterMain.cs new file mode 100644 index 0000000..33b87aa --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterMain.cs @@ -0,0 +1,270 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class GenericCharacterMain : BaseCharacterMain +{ + public delegate void MovementHitDelegate(ref CharacterMotor.MovementHitInfo movementHitInfo); + + private AimAnimator aimAnimator; + + protected bool jumpInputReceived; + + protected bool sprintInputReceived; + + private Vector3 moveVector = Vector3.zero; + + private Vector3 aimDirection = Vector3.forward; + + private int emoteRequest = -1; + + private bool hasAimAnimator; + + public override void OnEnter() + { + base.OnEnter(); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + aimAnimator = modelTransform.GetComponent(); + if ((bool)aimAnimator) + { + aimAnimator.enabled = true; + } + } + hasAimAnimator = aimAnimator; + } + + public override void OnExit() + { + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + AimAnimator component = modelTransform.GetComponent(); + if ((bool)component) + { + component.enabled = false; + } + } + if (base.isAuthority) + { + if ((bool)base.characterMotor) + { + base.characterMotor.moveDirection = Vector3.zero; + } + if ((bool)base.railMotor) + { + base.railMotor.inputMoveVector = Vector3.zero; + } + } + base.OnExit(); + } + + public override void Update() + { + base.Update(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + GatherInputs(); + HandleMovements(); + PerformInputs(); + } + + public virtual void HandleMovements() + { + if (useRootMotion) + { + if (hasCharacterMotor) + { + base.characterMotor.moveDirection = Vector3.zero; + } + if (hasRailMotor) + { + base.railMotor.inputMoveVector = moveVector; + } + } + else + { + if (hasCharacterMotor) + { + base.characterMotor.moveDirection = moveVector; + } + if (hasRailMotor) + { + base.railMotor.inputMoveVector = moveVector; + } + } + _ = base.isGrounded; + if (!hasRailMotor && hasCharacterDirection && hasCharacterBody) + { + if (hasAimAnimator && aimAnimator.aimType == AimAnimator.AimType.Smart) + { + Vector3 vector = ((moveVector == Vector3.zero) ? base.characterDirection.forward : moveVector); + float num = Vector3.Angle(aimDirection, vector); + float num2 = Mathf.Max(aimAnimator.pitchRangeMax + aimAnimator.pitchGiveupRange, aimAnimator.yawRangeMax + aimAnimator.yawGiveupRange); + base.characterDirection.moveVector = (((bool)base.characterBody && base.characterBody.shouldAim && num > num2) ? aimDirection : vector); + } + else + { + base.characterDirection.moveVector = (((bool)base.characterBody && base.characterBody.shouldAim) ? aimDirection : moveVector); + } + } + if (!base.isAuthority) + { + return; + } + ProcessJump(); + if (hasCharacterBody) + { + bool isSprinting = sprintInputReceived; + if (moveVector.magnitude <= 0.5f) + { + isSprinting = false; + } + base.characterBody.isSprinting = isSprinting; + } + } + + public static void ApplyJumpVelocity(CharacterMotor characterMotor, CharacterBody characterBody, float horizontalBonus, float verticalBonus, bool vault = false) + { + Vector3 moveDirection = characterMotor.moveDirection; + if (vault) + { + characterMotor.velocity = moveDirection; + } + else + { + moveDirection.y = 0f; + float magnitude = moveDirection.magnitude; + if (magnitude > 0f) + { + moveDirection /= magnitude; + } + Vector3 velocity = moveDirection * characterBody.moveSpeed * horizontalBonus; + velocity.y = characterBody.jumpPower * verticalBonus; + characterMotor.velocity = velocity; + } + characterMotor.Motor.ForceUnground(); + } + + public virtual void ProcessJump() + { + if (!hasCharacterMotor) + { + return; + } + bool flag = false; + bool flag2 = false; + if (!jumpInputReceived || !base.characterBody || base.characterMotor.jumpCount >= base.characterBody.maxJumpCount) + { + return; + } + int itemCount = base.characterBody.inventory.GetItemCount(RoR2Content.Items.JumpBoost); + float horizontalBonus = 1f; + float verticalBonus = 1f; + if (base.characterMotor.jumpCount >= base.characterBody.baseJumpCount) + { + flag = true; + horizontalBonus = 1.5f; + verticalBonus = 1.5f; + } + else if ((float)itemCount > 0f && base.characterBody.isSprinting) + { + float num = base.characterBody.acceleration * base.characterMotor.airControl; + if (base.characterBody.moveSpeed > 0f && num > 0f) + { + flag2 = true; + float num2 = Mathf.Sqrt(10f * (float)itemCount / num); + float num3 = base.characterBody.moveSpeed / num; + horizontalBonus = (num2 + num3) / num3; + } + } + ApplyJumpVelocity(base.characterMotor, base.characterBody, horizontalBonus, verticalBonus); + if (hasModelAnimator) + { + int layerIndex = base.modelAnimator.GetLayerIndex("Body"); + if (layerIndex >= 0) + { + if (base.characterMotor.jumpCount == 0 || base.characterBody.baseJumpCount == 1) + { + base.modelAnimator.CrossFadeInFixedTime("Jump", smoothingParameters.intoJumpTransitionTime, layerIndex); + } + else + { + base.modelAnimator.CrossFadeInFixedTime("BonusJump", smoothingParameters.intoJumpTransitionTime, layerIndex); + } + } + } + if (flag) + { + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/FeatherEffect"), new EffectData + { + origin = base.characterBody.footPosition + }, transmit: true); + } + else if (base.characterMotor.jumpCount > 0) + { + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/CharacterLandImpact"), new EffectData + { + origin = base.characterBody.footPosition, + scale = base.characterBody.radius + }, transmit: true); + } + if (flag2) + { + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/BoostJumpEffect"), new EffectData + { + origin = base.characterBody.footPosition, + rotation = Util.QuaternionSafeLookRotation(base.characterMotor.velocity) + }, transmit: true); + } + base.characterMotor.jumpCount++; + base.characterBody.onJump?.Invoke(); + } + + protected virtual bool CanExecuteSkill(GenericSkill skillSlot) + { + return true; + } + + protected void PerformInputs() + { + if (base.isAuthority) + { + if (hasSkillLocator) + { + HandleSkill(base.skillLocator.primary, ref base.inputBank.skill1); + HandleSkill(base.skillLocator.secondary, ref base.inputBank.skill2); + HandleSkill(base.skillLocator.utility, ref base.inputBank.skill3); + HandleSkill(base.skillLocator.special, ref base.inputBank.skill4); + } + jumpInputReceived = false; + sprintInputReceived = false; + } + void HandleSkill(GenericSkill skillSlot, ref InputBankTest.ButtonState buttonState) + { + if (buttonState.down && (bool)skillSlot && (!skillSlot.mustKeyPress || !buttonState.hasPressBeenClaimed) && CanExecuteSkill(skillSlot) && skillSlot.ExecuteIfReady()) + { + buttonState.hasPressBeenClaimed = true; + } + } + } + + protected void GatherInputs() + { + if (hasInputBank) + { + moveVector = base.inputBank.moveVector; + aimDirection = base.inputBank.aimDirection; + emoteRequest = base.inputBank.emoteRequest; + base.inputBank.emoteRequest = -1; + jumpInputReceived |= base.inputBank.jump.justPressed; + jumpInputReceived &= !base.inputBank.jump.hasPressBeenClaimed; + sprintInputReceived |= base.inputBank.sprint.down; + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterPod.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterPod.cs new file mode 100644 index 0000000..ecedf7c --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterPod.cs @@ -0,0 +1,30 @@ +namespace EntityStates; + +public class GenericCharacterPod : BaseState +{ + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = false; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.enabled = false; + } + } + + public override void OnExit() + { + if ((bool)base.characterMotor) + { + base.characterMotor.enabled = true; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.enabled = true; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterSpawnState.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterSpawnState.cs new file mode 100644 index 0000000..a5a50a8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterSpawnState.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public abstract class GenericCharacterSpawnState : BaseState +{ + [SerializeField] + public float duration = 2f; + + [SerializeField] + public string spawnSoundString; + + private static int Spawn1StateHash = Animator.StringToHash("Spawn1"); + + private static int Spawn1ParamHash = Animator.StringToHash("Spawn1.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + Util.PlaySound(spawnSoundString, base.gameObject); + PlayAnimation("Body", Spawn1StateHash, Spawn1ParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterVehicleSeated.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterVehicleSeated.cs new file mode 100644 index 0000000..43fb4fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericCharacterVehicleSeated.cs @@ -0,0 +1,9 @@ +namespace EntityStates; + +public class GenericCharacterVehicleSeated : BaseState +{ + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Vehicle; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericProjectileBaseState.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericProjectileBaseState.cs new file mode 100644 index 0000000..a388438 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericProjectileBaseState.cs @@ -0,0 +1,125 @@ +using RoR2; +using RoR2.Projectile; +using UnityEngine; + +namespace EntityStates; + +public class GenericProjectileBaseState : BaseState +{ + [SerializeField] + public GameObject effectPrefab; + + [SerializeField] + public GameObject projectilePrefab; + + [SerializeField] + public float damageCoefficient; + + [SerializeField] + public float force; + + [SerializeField] + public float minSpread; + + [SerializeField] + public float maxSpread; + + [SerializeField] + public float baseDuration = 2f; + + [SerializeField] + public float recoilAmplitude = 1f; + + [SerializeField] + public string attackSoundString; + + [SerializeField] + public float projectilePitchBonus; + + [SerializeField] + public float baseDelayBeforeFiringProjectile; + + [SerializeField] + public string targetMuzzle; + + [SerializeField] + public float bloom; + + protected float stopwatch; + + protected float duration; + + protected float delayBeforeFiringProjectile; + + protected bool firedProjectile; + + public override void OnEnter() + { + base.OnEnter(); + stopwatch = 0f; + duration = baseDuration / attackSpeedStat; + delayBeforeFiringProjectile = baseDelayBeforeFiringProjectile / attackSpeedStat; + if ((bool)base.characterBody) + { + base.characterBody.SetAimTimer(2f); + } + PlayAnimation(duration); + } + + public override void OnExit() + { + base.OnExit(); + } + + protected virtual void PlayAnimation(float duration) + { + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= delayBeforeFiringProjectile && !firedProjectile) + { + firedProjectile = true; + FireProjectile(); + DoFireEffects(); + } + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + protected virtual void FireProjectile() + { + if (base.isAuthority) + { + Ray aimRay = GetAimRay(); + aimRay = ModifyProjectileAimRay(aimRay); + aimRay.direction = Util.ApplySpread(aimRay.direction, minSpread, maxSpread, 1f, 1f, 0f, projectilePitchBonus); + ProjectileManager.instance.FireProjectile(projectilePrefab, aimRay.origin, Util.QuaternionSafeLookRotation(aimRay.direction), base.gameObject, damageStat * damageCoefficient, force, Util.CheckRoll(critStat, base.characterBody.master)); + } + } + + protected virtual Ray ModifyProjectileAimRay(Ray aimRay) + { + return aimRay; + } + + protected virtual void DoFireEffects() + { + Util.PlaySound(attackSoundString, base.gameObject); + AddRecoil(-2f * recoilAmplitude, -3f * recoilAmplitude, -1f * recoilAmplitude, 1f * recoilAmplitude); + if ((bool)effectPrefab) + { + EffectManager.SimpleMuzzleFlash(effectPrefab, base.gameObject, targetMuzzle, transmit: false); + } + base.characterBody.AddSpreadBloom(bloom); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GenericReload.cs b/ilspy_dump/ror2_csproj/EntityStates/GenericReload.cs new file mode 100644 index 0000000..fe54579 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GenericReload.cs @@ -0,0 +1,41 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class GenericReload : BaseState +{ + [SerializeField] + public string enterSoundString; + + protected float duration; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.skillLocator && (bool)base.skillLocator.primary) + { + duration = base.skillLocator.primary.CalculateFinalRechargeInterval(); + } + Util.PlaySound(enterSoundString, base.gameObject); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge > duration) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + base.OnExit(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/GhostUtilitySkillState.cs b/ilspy_dump/ror2_csproj/EntityStates/GhostUtilitySkillState.cs new file mode 100644 index 0000000..c2b953d --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/GhostUtilitySkillState.cs @@ -0,0 +1,255 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates; + +public class GhostUtilitySkillState : GenericCharacterMain +{ + public static float baseDuration; + + public static GameObject coreVfxPrefab; + + public static GameObject footVfxPrefab; + + public static GameObject entryEffectPrefab; + + public static GameObject exitEffectPrefab; + + public static float moveSpeedCoefficient; + + public static float healFractionPerTick; + + public static float healFrequency; + + private HurtBoxGroup hurtBoxGroup; + + private CharacterModel characterModel; + + private GameObject coreVfxInstance; + + private GameObject footVfxInstance; + + private float healTimer; + + private float duration; + + private ICharacterGravityParameterProvider characterGravityParameterProvider; + + private ICharacterFlightParameterProvider characterFlightParameterProvider; + + [SerializeField] + public string animationLayerName; + + [SerializeField] + public string animationStateName; + + [SerializeField] + public string playbackRateParam; + + private EffectManagerHelper _emh_coreVfxInstance; + + private EffectManagerHelper _emh_footVfxInstance; + + public override void Reset() + { + base.Reset(); + hurtBoxGroup = null; + characterModel = null; + coreVfxInstance = null; + footVfxInstance = null; + healTimer = 0f; + duration = 0f; + _emh_coreVfxInstance = null; + _emh_footVfxInstance = null; + } + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration; + characterGravityParameterProvider = base.gameObject.GetComponent(); + characterFlightParameterProvider = base.gameObject.GetComponent(); + if ((bool)base.characterBody) + { + if ((bool)base.characterBody.inventory) + { + duration *= base.characterBody.inventory.GetItemCount(RoR2Content.Items.LunarUtilityReplacement); + } + hurtBoxGroup = base.characterBody.hurtBoxGroup; + if ((bool)hurtBoxGroup) + { + HurtBoxGroup obj = hurtBoxGroup; + int hurtBoxesDeactivatorCounter = obj.hurtBoxesDeactivatorCounter + 1; + obj.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)coreVfxPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(coreVfxPrefab)) + { + coreVfxInstance = Object.Instantiate(coreVfxPrefab); + } + else + { + _emh_coreVfxInstance = EffectManager.GetAndActivatePooledEffect(coreVfxPrefab, Vector3.zero, Quaternion.identity); + coreVfxInstance = _emh_coreVfxInstance.gameObject; + } + } + if ((bool)footVfxPrefab) + { + if (!EffectManager.ShouldUsePooledEffect(footVfxPrefab)) + { + footVfxInstance = Object.Instantiate(footVfxPrefab); + } + else + { + _emh_footVfxInstance = EffectManager.GetAndActivatePooledEffect(footVfxPrefab, Vector3.zero, Quaternion.identity); + footVfxInstance = _emh_footVfxInstance.gameObject; + } + } + UpdateVfxPositions(); + if ((bool)entryEffectPrefab) + { + Ray aimRay = GetAimRay(); + EffectManager.SimpleEffect(entryEffectPrefab, aimRay.origin, Quaternion.LookRotation(aimRay.direction), transmit: false); + } + } + characterModel = GetModelTransform()?.GetComponent(); + if ((bool)base.modelAnimator) + { + base.modelAnimator.enabled = false; + } + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = moveSpeedCoefficient; + } + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount++; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount++; + characterFlightParameterProvider.flightParameters = flightParameters; + } + if ((bool)characterModel) + { + characterModel.invisibilityCount++; + } + EntityStateMachine[] components = base.gameObject.GetComponents(); + foreach (EntityStateMachine entityStateMachine in components) + { + if (entityStateMachine.customName == "Weapon") + { + entityStateMachine.SetNextStateToMain(); + } + } + } + + private void UpdateVfxPositions() + { + if ((bool)base.characterBody) + { + if ((bool)coreVfxInstance) + { + coreVfxInstance.transform.position = base.characterBody.corePosition; + } + if ((bool)footVfxInstance) + { + footVfxInstance.transform.position = base.characterBody.footPosition; + } + } + } + + protected override bool CanExecuteSkill(GenericSkill skillSlot) + { + return false; + } + + public override void Update() + { + base.Update(); + UpdateVfxPositions(); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + healTimer -= GetDeltaTime(); + if (healTimer <= 0f) + { + if (NetworkServer.active) + { + base.healthComponent.HealFraction(healFractionPerTick, default(ProcChainMask)); + } + healTimer = 1f / healFrequency; + } + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if ((bool)exitEffectPrefab && !outer.destroying) + { + Ray aimRay = GetAimRay(); + EffectManager.SimpleEffect(exitEffectPrefab, aimRay.origin, Quaternion.LookRotation(aimRay.direction), transmit: false); + } + if (_emh_coreVfxInstance != null && _emh_coreVfxInstance.OwningPool != null) + { + _emh_coreVfxInstance.OwningPool.ReturnObject(_emh_coreVfxInstance); + } + else if (coreVfxInstance != null) + { + EntityState.Destroy(coreVfxInstance); + } + coreVfxInstance = null; + _emh_coreVfxInstance = null; + if (_emh_footVfxInstance != null && _emh_footVfxInstance.OwningPool != null) + { + _emh_footVfxInstance.OwningPool.ReturnObject(_emh_footVfxInstance); + } + else if (footVfxInstance != null) + { + EntityState.Destroy(footVfxInstance); + } + footVfxInstance = null; + _emh_footVfxInstance = null; + if ((bool)characterModel) + { + characterModel.invisibilityCount--; + } + if ((bool)hurtBoxGroup) + { + HurtBoxGroup obj = hurtBoxGroup; + int hurtBoxesDeactivatorCounter = obj.hurtBoxesDeactivatorCounter - 1; + obj.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter; + } + if ((bool)base.modelAnimator) + { + base.modelAnimator.enabled = true; + } + if (characterFlightParameterProvider != null) + { + CharacterFlightParameters flightParameters = characterFlightParameterProvider.flightParameters; + flightParameters.channeledFlightGranterCount--; + characterFlightParameterProvider.flightParameters = flightParameters; + } + if (characterGravityParameterProvider != null) + { + CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; + gravityParameters.channeledAntiGravityGranterCount--; + characterGravityParameterProvider.gravityParameters = gravityParameters; + } + if ((bool)base.characterMotor) + { + base.characterMotor.walkSpeedPenaltyCoefficient = 1f; + } + base.OnExit(); + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/HoverState.cs b/ilspy_dump/ror2_csproj/EntityStates/HoverState.cs new file mode 100644 index 0000000..bbe9c1a --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/HoverState.cs @@ -0,0 +1,82 @@ +using UnityEngine; + +namespace EntityStates; + +public class HoverState : BaseState +{ + private Animator modelAnimator; + + private bool skill1InputReceived; + + private bool skill2InputReceived; + + private bool skill3InputReceived; + + private bool skill4InputReceived; + + private static int IdleStateHash = Animator.StringToHash("Idle"); + + private static int flyrateParamHash = Animator.StringToHash("fly.rate"); + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + PlayAnimation("Body", IdleStateHash); + } + + public override void Update() + { + base.Update(); + if ((bool)base.inputBank) + { + skill1InputReceived = base.inputBank.skill1.down; + skill2InputReceived = base.inputBank.skill2.down; + skill3InputReceived = base.inputBank.skill3.down; + skill4InputReceived = base.inputBank.skill4.down; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (!base.isAuthority) + { + return; + } + if ((bool)base.inputBank) + { + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = base.inputBank.moveVector * base.characterBody.moveSpeed; + if ((bool)modelAnimator) + { + modelAnimator.SetFloat(flyrateParamHash, Vector3.Magnitude(base.rigidbodyMotor.rigid.velocity)); + } + } + if ((bool)base.rigidbodyDirection) + { + base.rigidbodyDirection.aimDirection = GetAimRay().direction; + } + } + if ((bool)base.skillLocator) + { + if ((bool)base.skillLocator.primary && skill1InputReceived) + { + base.skillLocator.primary.ExecuteIfReady(); + } + if ((bool)base.skillLocator.secondary && skill2InputReceived) + { + base.skillLocator.secondary.ExecuteIfReady(); + } + if ((bool)base.skillLocator.utility && skill3InputReceived) + { + base.skillLocator.utility.ExecuteIfReady(); + } + if ((bool)base.skillLocator.special && skill4InputReceived) + { + base.skillLocator.special.ExecuteIfReady(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/HurtState.cs b/ilspy_dump/ror2_csproj/EntityStates/HurtState.cs new file mode 100644 index 0000000..44268dd --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/HurtState.cs @@ -0,0 +1,42 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class HurtState : BaseState +{ + private float stopwatch; + + private float duration = 0.35f; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.CrossFadeInFixedTime((Random.Range(0, 2) == 0) ? "Hurt1" : "Hurt2", 0.1f); + modelAnimator.Update(0f); + duration = modelAnimator.GetNextAnimatorStateInfo(layerIndex).length; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/HurtStateFlyer.cs b/ilspy_dump/ror2_csproj/EntityStates/HurtStateFlyer.cs new file mode 100644 index 0000000..b1a2543 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/HurtStateFlyer.cs @@ -0,0 +1,38 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class HurtStateFlyer : BaseState +{ + private float stopwatch; + + private float duration = 0.35f; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.sfxLocator && base.sfxLocator.deathSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.CrossFadeInFixedTime((Random.Range(0, 2) == 0) ? "Hurt1" : "Hurt2", 0.1f); + modelAnimator.Update(0f); + duration = modelAnimator.GetNextAnimatorStateInfo(layerIndex).length; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + stopwatch += GetDeltaTime(); + if (stopwatch >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/ISkillOverrideHandoff.cs b/ilspy_dump/ror2_csproj/EntityStates/ISkillOverrideHandoff.cs new file mode 100644 index 0000000..2b439c8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/ISkillOverrideHandoff.cs @@ -0,0 +1,6 @@ +namespace EntityStates; + +public interface ISkillOverrideHandoff +{ + void TransferSkillOverride(SkillStateOverrideData skillOverrideData); +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/ISkillState.cs b/ilspy_dump/ror2_csproj/EntityStates/ISkillState.cs new file mode 100644 index 0000000..c8d37d9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/ISkillState.cs @@ -0,0 +1,8 @@ +using RoR2; + +namespace EntityStates; + +public interface ISkillState +{ + GenericSkill activatorSkillSlot { get; set; } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/Idle.cs b/ilspy_dump/ror2_csproj/EntityStates/Idle.cs new file mode 100644 index 0000000..bb3cac8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/Idle.cs @@ -0,0 +1,5 @@ +namespace EntityStates; + +public class Idle : EntityState +{ +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/IdleSkillOverrideHandoff.cs b/ilspy_dump/ror2_csproj/EntityStates/IdleSkillOverrideHandoff.cs new file mode 100644 index 0000000..d760af1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/IdleSkillOverrideHandoff.cs @@ -0,0 +1,51 @@ +namespace EntityStates; + +public class IdleSkillOverrideHandoff : EntityState, ISkillOverrideHandoff +{ + public static float skillOverrideTimeout = 0.05f; + + private bool shouldProcess; + + private SkillStateOverrideData skillOverrideData; + + public void TransferSkillOverride(SkillStateOverrideData skillOverrideData) + { + this.skillOverrideData = skillOverrideData; + shouldProcess = this.skillOverrideData != null; + } + + public override void Update() + { + if (shouldProcess) + { + base.Update(); + skillOverrideData.StepRestock(); + if (base.age > skillOverrideTimeout) + { + skillOverrideData.ClearOverrides(); + skillOverrideData = null; + shouldProcess = false; + } + } + } + + public override void ModifyNextState(EntityState nextState) + { + base.ModifyNextState(nextState); + if (skillOverrideData != null && nextState is ISkillOverrideHandoff skillOverrideHandoff) + { + skillOverrideHandoff.TransferSkillOverride(skillOverrideData); + skillOverrideData = null; + shouldProcess = false; + } + } + + public override void OnExit() + { + base.OnExit(); + if (shouldProcess) + { + skillOverrideData?.ClearOverrides(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/InterruptPriority.cs b/ilspy_dump/ror2_csproj/EntityStates/InterruptPriority.cs new file mode 100644 index 0000000..cf4f7be --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/InterruptPriority.cs @@ -0,0 +1,13 @@ +namespace EntityStates; + +public enum InterruptPriority +{ + Any, + Skill, + PrioritySkill, + Pain, + Stun, + Frozen, + Vehicle, + Death +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/LockSkill.cs b/ilspy_dump/ror2_csproj/EntityStates/LockSkill.cs new file mode 100644 index 0000000..71bfb02 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/LockSkill.cs @@ -0,0 +1,9 @@ +namespace EntityStates; + +public class LockSkill : BaseState +{ + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/MageCalibrate.cs b/ilspy_dump/ror2_csproj/EntityStates/MageCalibrate.cs new file mode 100644 index 0000000..7769d61 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/MageCalibrate.cs @@ -0,0 +1,55 @@ +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates; + +public class MageCalibrate : BaseState +{ + public MageElement element; + + public MageCalibrationController calibrationController; + + private bool shouldApply; + + public override void OnEnter() + { + calibrationController = GetComponent(); + shouldApply = NetworkServer.active; + base.OnEnter(); + } + + public override void OnExit() + { + ApplyElement(); + base.OnExit(); + } + + public override void FixedUpdate() + { + outer.SetNextStateToMain(); + } + + private void ApplyElement() + { + if (shouldApply && (bool)calibrationController) + { + shouldApply = false; + calibrationController.SetElement(element); + } + } + + public override void OnSerialize(NetworkWriter writer) + { + writer.Write((byte)element); + } + + public override void OnDeserialize(NetworkReader reader) + { + element = (MageElement)reader.ReadByte(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/PrepFlower2.cs b/ilspy_dump/ror2_csproj/EntityStates/PrepFlower2.cs new file mode 100644 index 0000000..15a76ea --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/PrepFlower2.cs @@ -0,0 +1,39 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class PrepFlower2 : BaseState +{ + public static float baseDuration; + + public static string enterSoundString; + + private float duration; + + private static int PrepFlowerStateHash = Animator.StringToHash("PrepFlower"); + + private static int PrepFlowerParamHash = Animator.StringToHash("PrepFlower.playbackRate"); + + public override void OnEnter() + { + base.OnEnter(); + duration = baseDuration / attackSpeedStat; + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Gesture, Additive", PrepFlowerStateHash, PrepFlowerParamHash, duration); + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration) + { + outer.SetNextState(new FireFlower2()); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.PrioritySkill; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/SerializableEntityStateType.cs b/ilspy_dump/ror2_csproj/EntityStates/SerializableEntityStateType.cs new file mode 100644 index 0000000..c721198 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/SerializableEntityStateType.cs @@ -0,0 +1,65 @@ +using System; +using UnityEngine; + +namespace EntityStates; + +[Serializable] +public struct SerializableEntityStateType +{ + private Type _stateType; + + [SerializeField] + private string _typeName; + + public string typeName + { + get + { + return _typeName; + } + private set + { + stateType = Type.GetType(value); + } + } + + public Type stateType + { + get + { + if (_stateType == null) + { + CacheStateType(); + return _stateType; + } + return _stateType; + } + set + { + _typeName = ((value != null && value.IsSubclassOf(typeof(EntityState))) ? value.AssemblyQualifiedName : ""); + } + } + + public SerializableEntityStateType(string typeName) + { + _typeName = ""; + _stateType = null; + this.typeName = typeName; + } + + public SerializableEntityStateType(Type stateType) + { + _typeName = ""; + _stateType = null; + this.stateType = stateType; + } + + private void CacheStateType() + { + if (_typeName != null) + { + Type type = Type.GetType(_typeName); + _stateType = ((type != null && type.IsSubclassOf(typeof(EntityState))) ? type : null); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/ShockState.cs b/ilspy_dump/ror2_csproj/EntityStates/ShockState.cs new file mode 100644 index 0000000..a3b8f90 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/ShockState.cs @@ -0,0 +1,118 @@ +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class ShockState : BaseState +{ + public static GameObject stunVfxPrefab; + + public float shockDuration = 1f; + + public static float shockInterval = 0.1f; + + public static float shockStrength = 1f; + + public static float healthFractionToForceExit = 0.1f; + + public static string enterSoundString; + + public static string exitSoundString; + + private float shockTimer; + + private Animator animator; + + private TemporaryOverlayInstance temporaryOverlay; + + private float healthFraction; + + private GameObject stunVfxInstance; + + private static int Hurt1StateHash = Animator.StringToHash("Hurt1"); + + private static int Hurt2StateHash = Animator.StringToHash("Hurt2"); + + public override void OnEnter() + { + base.OnEnter(); + animator = GetModelAnimator(); + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + Util.PlaySound(enterSoundString, base.gameObject); + PlayAnimation("Body", (Random.Range(0, 2) == 0) ? Hurt1StateHash : Hurt2StateHash); + Transform modelTransform = GetModelTransform(); + if ((bool)modelTransform) + { + CharacterModel component = modelTransform.GetComponent(); + if ((bool)component) + { + temporaryOverlay = TemporaryOverlayManager.AddOverlay(base.gameObject); + temporaryOverlay.duration = shockDuration; + temporaryOverlay.originalMaterial = LegacyResourcesAPI.Load("Materials/matIsShocked"); + temporaryOverlay.AddToCharacterModel(component); + } + } + stunVfxInstance = Object.Instantiate(stunVfxPrefab, base.transform); + stunVfxInstance.GetComponent().newDuration = shockDuration; + if ((bool)base.characterBody.healthComponent) + { + healthFraction = base.characterBody.healthComponent.combinedHealthFraction; + } + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + shockTimer -= GetDeltaTime(); + float combinedHealthFraction = base.characterBody.healthComponent.combinedHealthFraction; + if (shockTimer <= 0f) + { + shockTimer += shockInterval; + PlayShockAnimation(); + } + if (base.fixedAge > shockDuration || healthFraction - combinedHealthFraction > healthFractionToForceExit) + { + outer.SetNextStateToMain(); + } + } + + public override void OnExit() + { + if (temporaryOverlay != null) + { + temporaryOverlay.Destroy(); + } + if ((bool)stunVfxInstance) + { + EntityState.Destroy(stunVfxInstance); + } + Util.PlaySound(exitSoundString, base.gameObject); + base.OnExit(); + } + + private void PlayShockAnimation() + { + string layerName = "Flinch"; + int layerIndex = animator.GetLayerIndex(layerName); + if (layerIndex >= 0) + { + animator.SetLayerWeight(layerIndex, shockStrength); + animator.Play("FlinchStart", layerIndex); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/SkillStateMethods.cs b/ilspy_dump/ror2_csproj/EntityStates/SkillStateMethods.cs new file mode 100644 index 0000000..3469c8f --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/SkillStateMethods.cs @@ -0,0 +1,45 @@ +using System; +using RoR2; +using UnityEngine.Networking; + +namespace EntityStates; + +public static class SkillStateMethods +{ + public static void Serialize(this ISkillState skillState, SkillLocator skillLocator, NetworkWriter writer) + { + int num = -1; + if ((object)skillLocator != null) + { + num = skillLocator.GetSkillSlotIndex(skillState.activatorSkillSlot); + } + writer.Write((sbyte)num); + } + + public static void Deserialize(this ISkillState skillState, SkillLocator skillLocator, NetworkReader reader) + { + int index = reader.ReadSByte(); + if ((object)skillLocator != null) + { + skillState.activatorSkillSlot = skillLocator.GetSkillAtIndex(index); + } + } + + public static bool IsKeyDownAuthority(this ISkillState skillState, SkillLocator skillLocator, InputBankTest inputBank) + { + GenericSkill activatorSkillSlot = skillState.activatorSkillSlot; + if ((object)skillLocator == null || (object)activatorSkillSlot == null || (object)inputBank == null) + { + return false; + } + return skillLocator.FindSkillSlot(activatorSkillSlot) switch + { + SkillSlot.None => false, + SkillSlot.Primary => inputBank.skill1.down, + SkillSlot.Secondary => inputBank.skill2.down, + SkillSlot.Utility => inputBank.skill3.down, + SkillSlot.Special => inputBank.skill4.down, + _ => throw new ArgumentOutOfRangeException(), + }; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/SkillStateOverrideData.cs b/ilspy_dump/ror2_csproj/EntityStates/SkillStateOverrideData.cs new file mode 100644 index 0000000..04e3fc3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/SkillStateOverrideData.cs @@ -0,0 +1,142 @@ +using RoR2; +using RoR2.Skills; +using UnityEngine; + +namespace EntityStates; + +public class SkillStateOverrideData +{ + private object source; + + public bool duplicateStock; + + public bool overrideFullReloadOnAssign; + + public bool simulateRestockForOverridenSkills = true; + + private static GenericSkill.SkillOverridePriority priority = GenericSkill.SkillOverridePriority.Contextual; + + private float overrideTimestamp; + + public SkillDef primarySkillOverride; + + public SkillDef secondarySkillOverride; + + public SkillDef utilitySkillOverride; + + public SkillDef specialSkillOverride; + + private GenericSkill primarySkillOriginal; + + private GenericSkill secondarySkillOriginal; + + private GenericSkill utilitySkillOriginal; + + private GenericSkill specialSkillOriginal; + + public int previousPrimaryStock = -1; + + public int previousSecondaryStock = -1; + + public int previousUtilityStock = -1; + + public int previousSpecialStock = -1; + + public bool hasAuthority { get; private set; } + + public SkillStateOverrideData(CharacterBody sourceBody) + { + source = sourceBody; + hasAuthority = Util.HasEffectiveAuthority(sourceBody.gameObject); + duplicateStock = false; + } + + public SkillStateOverrideData(CharacterBody sourceBody, bool _duplicateStock) + { + source = sourceBody; + hasAuthority = Util.HasEffectiveAuthority(sourceBody.gameObject); + duplicateStock = _duplicateStock; + } + + public void OverrideSkills(SkillLocator skillLocator) + { + if (hasAuthority && !(skillLocator == null)) + { + overrideTimestamp = Time.time; + InternalOverride(skillLocator.primary, ref primarySkillOverride, ref primarySkillOriginal, ref previousPrimaryStock); + InternalOverride(skillLocator.secondary, ref secondarySkillOverride, ref secondarySkillOriginal, ref previousSecondaryStock); + InternalOverride(skillLocator.utility, ref utilitySkillOverride, ref utilitySkillOriginal, ref previousUtilityStock); + InternalOverride(skillLocator.special, ref specialSkillOverride, ref specialSkillOriginal, ref previousSpecialStock); + } + } + + private void InternalOverride(GenericSkill existingSkillToOverride, ref SkillDef overridingSkill, ref GenericSkill originalSkill, ref int previousStockAmount) + { + if (!(overridingSkill == null) && !(existingSkillToOverride == null) && !(existingSkillToOverride == originalSkill) && !existingSkillToOverride.HasSkillOverrideOfPriority(priority)) + { + int stock = existingSkillToOverride.stock; + previousStockAmount = -1; + originalSkill = existingSkillToOverride; + originalSkill.SetSkillOverride(source, overridingSkill, priority); + if (duplicateStock) + { + originalSkill.stock = stock; + } + } + } + + public void ClearOverrides() + { + if (hasAuthority && source != null) + { + InternalClearOverride(ref primarySkillOriginal, ref primarySkillOverride, ref previousPrimaryStock); + InternalClearOverride(ref secondarySkillOriginal, ref secondarySkillOverride, ref previousSecondaryStock); + InternalClearOverride(ref utilitySkillOriginal, ref utilitySkillOverride, ref previousUtilityStock); + InternalClearOverride(ref specialSkillOriginal, ref specialSkillOverride, ref previousSpecialStock); + } + void InternalClearOverride(ref GenericSkill overriddenSkill, ref SkillDef skillDef, ref int previousStockAmount) + { + if (!(overriddenSkill == null) && !(skillDef == null) && overriddenSkill.HasSkillOverrideOfPriority(priority)) + { + int baseStock = overriddenSkill.GetBaseStock(); + int stock = overriddenSkill.stock; + float rechargeStopwatch = overriddenSkill.rechargeStopwatch; + overriddenSkill.UnsetSkillOverride(source, skillDef, priority); + if (overrideFullReloadOnAssign && overriddenSkill.skillDef.fullRestockOnAssign) + { + overriddenSkill.stock = baseStock; + } + if (simulateRestockForOverridenSkills) + { + overriddenSkill.RechargeBaseSkill(Time.time - overrideTimestamp); + } + previousStockAmount = -1; + if (duplicateStock) + { + overriddenSkill.baseStock = stock; + overriddenSkill.baseRechargeStopwatch = rechargeStopwatch; + } + } + } + } + + public void StepRestock() + { + float time2 = Time.time; + if (!(time2 <= overrideTimestamp)) + { + InternalRestock(time2, ref primarySkillOriginal); + InternalRestock(time2, ref secondarySkillOriginal); + InternalRestock(time2, ref utilitySkillOriginal); + InternalRestock(time2, ref specialSkillOriginal); + overrideTimestamp = time2; + } + void InternalRestock(float time, ref GenericSkill overridenSkill) + { + if (!(overridenSkill == null)) + { + overridenSkill.RechargeBaseSkill(time - overrideTimestamp); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/SleepState.cs b/ilspy_dump/ror2_csproj/EntityStates/SleepState.cs new file mode 100644 index 0000000..e525289 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/SleepState.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace EntityStates; + +public class SleepState : EntityState +{ + public override void OnEnter() + { + base.OnEnter(); + Animator modelAnimator = GetModelAnimator(); + if ((bool)modelAnimator) + { + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.Play("Sleep", layerIndex, 0f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Any; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/SpawnTeleporterState.cs b/ilspy_dump/ror2_csproj/EntityStates/SpawnTeleporterState.cs new file mode 100644 index 0000000..ae62704 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/SpawnTeleporterState.cs @@ -0,0 +1,86 @@ +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +namespace EntityStates; + +public class SpawnTeleporterState : BaseState +{ + private float duration = 4f; + + public static string soundString; + + public static float initialDelay; + + private bool hasTeleported; + + private Animator modelAnimator; + + private PrintController printController; + + private CharacterModel characterModel; + + private CameraTargetParams.AimRequest aimRequest; + + public override void OnEnter() + { + base.OnEnter(); + modelAnimator = GetModelAnimator(); + if ((bool)base.cameraTargetParams) + { + aimRequest = base.cameraTargetParams.RequestAimType(CameraTargetParams.AimType.Aura); + } + if ((bool)modelAnimator) + { + GameObject gameObject = modelAnimator.gameObject; + characterModel = gameObject.GetComponent(); + characterModel.invisibilityCount++; + } + if (NetworkServer.active) + { + base.characterBody.AddBuff(RoR2Content.Buffs.HiddenInvincibility); + } + } + + public override void OnExit() + { + base.OnExit(); + if (!hasTeleported) + { + characterModel.invisibilityCount--; + } + aimRequest?.Dispose(); + if (NetworkServer.active) + { + base.characterBody.RemoveBuff(RoR2Content.Buffs.HiddenInvincibility); + base.characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, 3f); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= initialDelay && !hasTeleported) + { + hasTeleported = true; + characterModel.invisibilityCount--; + duration = initialDelay; + TeleportOutController.AddTPOutEffect(characterModel, 1f, 0f, duration); + GameObject teleportEffectPrefab = Run.instance.GetTeleportEffectPrefab(base.gameObject); + if ((bool)teleportEffectPrefab) + { + EffectManager.SimpleEffect(teleportEffectPrefab, base.transform.position, Quaternion.identity, transmit: false); + } + Util.PlaySound(soundString, base.gameObject); + } + if (base.fixedAge >= duration && hasTeleported && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Death; + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/StunState.cs b/ilspy_dump/ror2_csproj/EntityStates/StunState.cs new file mode 100644 index 0000000..ceb3d15 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/StunState.cs @@ -0,0 +1,139 @@ +using System; +using RoR2; +using UnityEngine; + +namespace EntityStates; + +public class StunState : BaseState +{ + private float duration; + + private GameObject stunVfxInstance; + + public float stunDuration = 0.35f; + + public static GameObject stunVfxPrefab; + + protected EffectManagerHelper _efhStunEffect; + + public float timeRemaining => Math.Max(duration - base.fixedAge, 0f); + + public override void Reset() + { + base.Reset(); + duration = 0f; + stunVfxInstance = null; + stunDuration = 0.35f; + _efhStunEffect = null; + } + + public override InterruptPriority GetMinimumInterruptPriority() + { + return InterruptPriority.Stun; + } + + public void ExtendStun(float durationDelta) + { + duration += durationDelta; + PlayStunAnimation(); + } + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)base.sfxLocator && base.sfxLocator.barkSound != "") + { + Util.PlaySound(base.sfxLocator.barkSound, base.gameObject); + } + PlayStunAnimation(); + if ((bool)base.characterBody) + { + base.characterBody.isSprinting = false; + } + if ((bool)base.characterDirection) + { + base.characterDirection.moveVector = base.characterDirection.forward; + } + if ((bool)base.rigidbodyMotor) + { + base.rigidbodyMotor.moveVector = Vector3.zero; + } + } + + private void PlayStunAnimation() + { + Animator modelAnimator = GetModelAnimator(); + if (!modelAnimator) + { + return; + } + int layerIndex = modelAnimator.GetLayerIndex("Body"); + modelAnimator.CrossFadeInFixedTime((UnityEngine.Random.Range(0, 2) == 0) ? "Hurt1" : "Hurt2", 0.1f); + modelAnimator.Update(0f); + AnimatorStateInfo nextAnimatorStateInfo = modelAnimator.GetNextAnimatorStateInfo(layerIndex); + duration = Mathf.Max(duration, Mathf.Max(stunDuration, nextAnimatorStateInfo.length)); + if (stunDuration >= 0f) + { + if ((bool)stunVfxInstance) + { + ReleaseStunVFX(); + } + if (!EffectManager.ShouldUsePooledEffect(stunVfxPrefab)) + { + stunVfxInstance = UnityEngine.Object.Instantiate(stunVfxPrefab, base.transform); + } + else + { + _efhStunEffect = EffectManager.GetAndActivatePooledEffect(stunVfxPrefab, base.transform); + stunVfxInstance = _efhStunEffect.gameObject; + } + ScaleParticleSystemDuration component = stunVfxInstance.GetComponent(); + component.newDuration = duration; + component.UpdateDuration(); + } + } + + public override void OnExit() + { + ReleaseStunVFX(); + base.OnExit(); + } + + private void ReleaseStunVFX() + { + if (!stunVfxInstance) + { + return; + } + if (!EffectManager.UsePools) + { + EntityState.Destroy(stunVfxInstance); + } + else if (_efhStunEffect != null && _efhStunEffect.OwningPool != null) + { + if (!_efhStunEffect.OwningPool.IsObjectInPool(_efhStunEffect)) + { + _efhStunEffect.OwningPool.ReturnObject(_efhStunEffect); + } + } + else + { + if (_efhStunEffect != null) + { + Debug.LogFormat("StunEffect has no owning pool {0} {1}", base.gameObject.name, base.gameObject.GetInstanceID()); + } + EntityState.Destroy(stunVfxInstance); + } + _efhStunEffect = null; + stunVfxInstance = null; + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (base.fixedAge >= duration && base.isAuthority) + { + outer.SetNextStateToMain(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/TestState1.cs b/ilspy_dump/ror2_csproj/EntityStates/TestState1.cs new file mode 100644 index 0000000..7612eb8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/TestState1.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +namespace EntityStates; + +public class TestState1 : EntityState +{ + public override void OnEnter() + { + Debug.LogFormat("{0} Entering TestState1.", base.gameObject); + } + + public override void OnExit() + { + Debug.LogFormat("{0} Exiting TestState1.", base.gameObject); + } + + public override void FixedUpdate() + { + if (base.isAuthority && Input.GetButton("Fire1")) + { + outer.SetNextState(new TestState2()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/TestState2.cs b/ilspy_dump/ror2_csproj/EntityStates/TestState2.cs new file mode 100644 index 0000000..359779e --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/TestState2.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +namespace EntityStates; + +public class TestState2 : EntityState +{ + public override void OnEnter() + { + Debug.LogFormat("{0} Entering TestState2.", base.gameObject); + } + + public override void OnExit() + { + Debug.LogFormat("{0} Exiting TestState2.", base.gameObject); + } + + public override void FixedUpdate() + { + if (base.isAuthority && Input.GetButton("Fire2")) + { + outer.SetNextState(new TestState1()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/EntityStates/Uninitialized.cs b/ilspy_dump/ror2_csproj/EntityStates/Uninitialized.cs new file mode 100644 index 0000000..59d8624 --- /dev/null +++ b/ilspy_dump/ror2_csproj/EntityStates/Uninitialized.cs @@ -0,0 +1,5 @@ +namespace EntityStates; + +public class Uninitialized : EntityState +{ +} diff --git a/ilspy_dump/ror2_csproj/FPSCounter.cs b/ilspy_dump/ror2_csproj/FPSCounter.cs new file mode 100644 index 0000000..2b399ef --- /dev/null +++ b/ilspy_dump/ror2_csproj/FPSCounter.cs @@ -0,0 +1,235 @@ +using System; +using RoR2; +using TMPro; +using UnityEngine; + +public class FPSCounter : MonoBehaviour +{ + private TextMeshProUGUI unityText; + + private TextMeshProUGUI unityVarText; + + private TextMeshProUGUI cpuText; + + private TextMeshProUGUI gpuText; + + private TextMeshProUGUI memText; + + private static float[] unitySamples; + + private static float[] cpuSamples; + + private static float[] gpuSamples; + + public static int numSamples = 30; + + private static int sampleIndex = 0; + + private int frameSampleIndex; + + public GameObject rootObject; + + public float timingCaptureFrequency = 2f; + + private float captureTimer; + + private char[] tempArray = new char[64]; + + private uint numTimings = 5u; + + private FrameTiming[] outTimings; + + private long prevAllocatedBytes; + + private static int waitTurn = 0; + + private static int waitIndex = 0; + + private static int maxWaitIndex = 5; + + public static float currentFPS = 30f; + + private void Start() + { + RoR2Application.onUpdate += UpdateFPSLimitVars; + unitySamples = new float[numSamples]; + base.gameObject.SetActive(value: false); + } + + private int PutValue(int value, char[] array, int startIndex, bool addPlusIfPositive = false, bool disableMinusIfNegative = false) + { + if (value >= 0) + { + if (addPlusIfPositive) + { + array[startIndex] = '+'; + startIndex++; + } + } + else if (!disableMinusIfNegative) + { + value = -value; + array[startIndex] = '-'; + startIndex++; + } + int num = 10; + int num2 = 1; + while (num <= value && num != 0) + { + num *= 10; + num2++; + } + num /= 10; + if (num == 0) + { + num = 1; + } + for (int i = 0; i < num2; i++) + { + int digit = GetDigit(value, num); + num /= 10; + array[startIndex + i] = (char)(digit + 48); + } + return startIndex + num2; + } + + private int PutValue(int value, char[] array, int startIndex, int numDigits) + { + int num = 10; + int num2 = 1; + while (num <= value) + { + num *= 10; + num2++; + } + num /= 10; + if (num2 < numDigits) + { + for (int i = num2; i < numDigits; i++) + { + array[startIndex++] = '0'; + } + } + for (int j = 0; j < num2; j++) + { + int digit = GetDigit(value, num); + num /= 10; + array[startIndex + j] = (char)(digit + 48); + } + return startIndex + num2; + } + + private int PutValue(double value, char[] array, int startIndex, int numDecimalPlaces = 0, bool addPlusIfPositive = false) + { + int value2 = (int)value; + startIndex = PutValue(value2, array, startIndex, addPlusIfPositive); + if (numDecimalPlaces == 0) + { + return startIndex; + } + array[startIndex++] = '.'; + double num = 10.0; + for (int i = 1; i < numDecimalPlaces; i++) + { + num *= 10.0; + } + double num2 = Math.Abs(value); + int value3 = (int)((num2 - Math.Floor(num2)) * num); + startIndex = PutValue(value3, array, startIndex, numDecimalPlaces); + return startIndex; + } + + private int PutValue(float value, char[] array, int startIndex, int numDecimalPlaces = 0, bool addPlusIfPositive = false) + { + int value2 = (int)value; + startIndex = PutValue(value2, array, startIndex, addPlusIfPositive); + if (numDecimalPlaces == 0) + { + return startIndex; + } + array[startIndex++] = '.'; + float num = 10f; + for (int i = 1; i < numDecimalPlaces; i++) + { + num *= 10f; + } + float num2 = Mathf.Abs(value); + int value3 = (int)((num2 - Mathf.Floor(num2)) * num); + startIndex = PutValue(value3, array, startIndex, numDecimalPlaces); + return startIndex; + } + + private int PutValue(string value, char[] array, int startIndex) + { + for (int i = 0; i < value.Length; i++) + { + array[startIndex + i] = value[i]; + } + return startIndex + value.Length; + } + + private int GetDigit(int value, int place) + { + if (place == 1) + { + return value % 10; + } + int num = place * 10; + int num2 = value % num; + int num3 = value % place; + return (num2 - num3) / place; + } + + public static int GetWaitIndex() + { + waitIndex++; + if (waitIndex > maxWaitIndex) + { + waitIndex = 0; + } + return waitIndex; + } + + public static bool CheckFPSQueue(ref int waitIndex) + { + if (waitIndex == 0) + { + waitIndex = GetWaitIndex(); + } + if (currentFPS < 28f && waitIndex != waitTurn) + { + return false; + } + return true; + } + + private static void UpdateFPSLimitVars() + { + waitTurn++; + if (waitTurn > maxWaitIndex) + { + waitTurn = 0; + } + CalculateFramerate(); + } + + private static void CalculateFramerate() + { + unitySamples[sampleIndex++] = 1f / Time.unscaledDeltaTime; + if (sampleIndex == numSamples) + { + sampleIndex = 0; + } + float num = 0f; + for (int i = 0; i < numSamples; i++) + { + num += unitySamples[i]; + } + num /= (float)numSamples; + currentFPS = num; + } + + private void Update() + { + } +} diff --git a/ilspy_dump/ror2_csproj/FPSQueue.cs b/ilspy_dump/ror2_csproj/FPSQueue.cs new file mode 100644 index 0000000..90b99d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/FPSQueue.cs @@ -0,0 +1,75 @@ +using RoR2; +using UnityEngine; + +public class FPSQueue : MonoBehaviour +{ + public static float fpsThrottlingCutoff = 28f; + + public static float currentFPS = 30f; + + public static int numSamples = 30; + + private static int sampleIndex = 0; + + private static float[] unitySamples; + + private static int waitTurn = 0; + + private static int waitIndex = 0; + + private static int maxWaitIndex = 5; + + private void Start() + { + RoR2Application.onUpdate += UpdateFPSLimitVars; + unitySamples = new float[numSamples]; + } + + public static int GetWaitIndex() + { + waitIndex++; + if (waitIndex > maxWaitIndex) + { + waitIndex = 0; + } + return waitIndex; + } + + public static bool CheckFPSQueue(ref int waitIndex) + { + if (waitIndex == 0) + { + waitIndex = GetWaitIndex(); + } + if (currentFPS < fpsThrottlingCutoff && waitIndex != waitTurn) + { + return false; + } + return true; + } + + private static void UpdateFPSLimitVars() + { + waitTurn++; + if (waitTurn > maxWaitIndex) + { + waitTurn = 0; + } + CalculateFramerate(); + } + + private static void CalculateFramerate() + { + unitySamples[sampleIndex++] = 1f / Time.unscaledDeltaTime; + if (sampleIndex == numSamples) + { + sampleIndex = 0; + } + float num = 0f; + for (int i = 0; i < numSamples; i++) + { + num += unitySamples[i]; + } + currentFPS = num / (float)numSamples; + } +} diff --git a/ilspy_dump/ror2_csproj/FastDebug.cs b/ilspy_dump/ror2_csproj/FastDebug.cs new file mode 100644 index 0000000..743e1ef --- /dev/null +++ b/ilspy_dump/ror2_csproj/FastDebug.cs @@ -0,0 +1,116 @@ +using System; +using System.Diagnostics; +using RoR2; +using UnityEngine; + +public static class FastDebug +{ + [Conditional("YEET")] + public static void Log(object message, UnityEngine.Object context) + { + UnityEngine.Debug.Log(message, context); + } + + [Conditional("YEET")] + public static void Log(object message) + { + UnityEngine.Debug.Log(message); + } + + [Conditional("YEET")] + public static void LogFormat(string message, params object[] args) + { + UnityEngine.Debug.LogFormat(message, args); + } + + [Conditional("YEET")] + public static void LogFormat(UnityEngine.Object context, string message, params object[] args) + { + UnityEngine.Debug.LogFormat(context, message, args); + } + + [Conditional("YEET")] + public static void LogWarning(object message, UnityEngine.Object context) + { + UnityEngine.Debug.LogWarning(message, context); + } + + [Conditional("YEET")] + public static void LogWarning(object message) + { + UnityEngine.Debug.LogWarning(message); + } + + [Conditional("YEET")] + public static void LogWarningFormat(string message, params object[] args) + { + UnityEngine.Debug.LogWarningFormat(message, args); + } + + [Conditional("YEET")] + public static void LogWarningFormat(UnityEngine.Object context, string message, params object[] args) + { + UnityEngine.Debug.LogWarningFormat(context, message, args); + } + + [Conditional("YEET")] + public static void LogError(object message, UnityEngine.Object context) + { + UnityEngine.Debug.LogError(message, context); + } + + [Conditional("YEET")] + public static void LogError(object message) + { + UnityEngine.Debug.LogError(message); + } + + [Conditional("YEET")] + public static void LogErrorFormat(string message, params object[] args) + { + UnityEngine.Debug.LogErrorFormat(message, args); + } + + [Conditional("YEET")] + public static void LogErrorFormat(UnityEngine.Object context, string message, params object[] args) + { + UnityEngine.Debug.LogErrorFormat(context, message, args); + } + + [Conditional("YEET")] + public static void LogAssertion(object message, UnityEngine.Object context) + { + } + + [Conditional("YEET")] + public static void LogAssertion(object message) + { + } + + [Conditional("YEET")] + public static void LogAssertionFormat(string message, params object[] args) + { + } + + [Conditional("YEET")] + public static void LogAssertion(UnityEngine.Object context, string message, params object[] args) + { + } + + [Conditional("YEET")] + public static void LogException(Exception e, UnityEngine.Object context) + { + UnityEngine.Debug.LogException(e, context); + } + + [Conditional("YEET")] + public static void LogException(Exception e) + { + UnityEngine.Debug.LogException(e); + } + + public static void LogChat(object message) + { + Chat.AddMessage(message.ToString()); + } +} diff --git a/ilspy_dump/ror2_csproj/FirstSelectedObjectProvider.cs b/ilspy_dump/ror2_csproj/FirstSelectedObjectProvider.cs new file mode 100644 index 0000000..4cfd218 --- /dev/null +++ b/ilspy_dump/ror2_csproj/FirstSelectedObjectProvider.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using RoR2.UI; +using UnityEngine; +using UnityEngine.UI; + +public class FirstSelectedObjectProvider : MonoBehaviour +{ + public GameObject firstSelectedObject; + + public GameObject[] fallBackFirstSelectedObjects; + + private GameObject lastSelected; + + public GameObject[] enforceCurrentSelectionIsInList; + + public bool takeAbsolutePriority; + + public static FirstSelectedObjectProvider priorityHolder; + + private void OnEnable() + { + if (takeAbsolutePriority) + { + priorityHolder = this; + } + } + + private void OnDisable() + { + if (takeAbsolutePriority && priorityHolder == this) + { + priorityHolder = null; + } + } + + private GameObject getInteractableFirstSelectedObject() + { + if ((bool)firstSelectedObject && firstSelectedObject.GetComponent().interactable && firstSelectedObject.activeInHierarchy) + { + return firstSelectedObject; + } + if (fallBackFirstSelectedObjects == null) + { + return null; + } + for (int i = 0; i < fallBackFirstSelectedObjects.Length; i++) + { + if (fallBackFirstSelectedObjects[i].GetComponent().interactable && fallBackFirstSelectedObjects[i].activeInHierarchy) + { + return fallBackFirstSelectedObjects[i]; + } + } + return null; + } + + public void EnsureSelectedObject() + { + if (priorityHolder != null && priorityHolder != this) + { + return; + } + GameObject interactableFirstSelectedObject = getInteractableFirstSelectedObject(); + if (!(interactableFirstSelectedObject != null)) + { + return; + } + MPEventSystemLocator component = interactableFirstSelectedObject.GetComponent(); + if (!component) + { + return; + } + MPEventSystem eventSystem = component.eventSystem; + if (!eventSystem) + { + return; + } + GameObject currentSelectedGameObject = eventSystem.currentSelectedGameObject; + if (currentSelectedGameObject == null) + { + if (lastSelected != null && lastSelected.GetComponent().interactable) + { + eventSystem.SetSelectedGameObject(lastSelected); + } + else + { + if (eventSystem.firstSelectedGameObject == null) + { + eventSystem.firstSelectedGameObject = interactableFirstSelectedObject; + } + eventSystem.SetSelectedGameObject(interactableFirstSelectedObject); + } + } + else + { + Selectable component2 = currentSelectedGameObject.GetComponent(); + bool flag = true; + if (enforceCurrentSelectionIsInList != null && enforceCurrentSelectionIsInList.Length != 0) + { + flag = false; + GameObject[] array = enforceCurrentSelectionIsInList; + for (int i = 0; i < array.Length; i++) + { + if (array[i] == currentSelectedGameObject) + { + flag = true; + } + } + } + if ((bool)component2 && (!component2.interactable || !component2.isActiveAndEnabled)) + { + flag = false; + } + if (!flag && (bool)component2 && (!component2.interactable || !component2.isActiveAndEnabled)) + { + eventSystem.SetSelectedGameObject(interactableFirstSelectedObject); + } + } + if (component.eventSystem.currentSelectedGameObject != null) + { + lastSelected = component.eventSystem.currentSelectedGameObject; + } + } + + public void ForceSelectFirstInteractable() + { + GameObject interactableFirstSelectedObject = getInteractableFirstSelectedObject(); + if (!(interactableFirstSelectedObject != null)) + { + return; + } + MPEventSystemLocator component = interactableFirstSelectedObject.GetComponent(); + if (!component) + { + return; + } + MPEventSystem eventSystem = component.eventSystem; + if ((bool)eventSystem) + { + if (eventSystem.firstSelectedGameObject == null) + { + eventSystem.firstSelectedGameObject = interactableFirstSelectedObject; + } + eventSystem.SetSelectedGameObject(interactableFirstSelectedObject); + } + if (component.eventSystem.currentSelectedGameObject != null) + { + lastSelected = component.eventSystem.currentSelectedGameObject; + } + } + + public void ResetLastSelected() + { + lastSelected = null; + } + + public void AddObject(GameObject obj, bool enforceCurrentSelection = false) + { + if (firstSelectedObject == null) + { + firstSelectedObject = obj; + } + else if (fallBackFirstSelectedObjects == null) + { + fallBackFirstSelectedObjects = new GameObject[1]; + fallBackFirstSelectedObjects[0] = obj; + } + else if (fallBackFirstSelectedObjects.Length >= 0) + { + List list = new List(fallBackFirstSelectedObjects); + list.Add(obj); + fallBackFirstSelectedObjects = list.ToArray(); + } + if (enforceCurrentSelection) + { + if (enforceCurrentSelectionIsInList == null) + { + enforceCurrentSelectionIsInList = new GameObject[1]; + enforceCurrentSelectionIsInList[0] = obj; + } + else if (enforceCurrentSelectionIsInList.Length >= 0) + { + List list2 = new List(enforceCurrentSelectionIsInList); + list2.Add(obj); + enforceCurrentSelectionIsInList = list2.ToArray(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/FlashWindow.cs b/ilspy_dump/ror2_csproj/FlashWindow.cs new file mode 100644 index 0000000..903ffe2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/FlashWindow.cs @@ -0,0 +1,164 @@ +using System; +using System.Runtime.InteropServices; +using RoR2; +using RoR2.Networking; +using UnityEngine.SceneManagement; + +public static class FlashWindow +{ + private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + + private struct FLASHWINFO + { + public uint cbSize; + + public IntPtr hwnd; + + public uint dwFlags; + + public uint uCount; + + public uint dwTimeout; + } + + private static IntPtr myWindow; + + private static readonly IntPtr myProcessId = GetCurrentProcessId(); + + public const uint FLASHW_STOP = 0u; + + public const uint FLASHW_CAPTION = 1u; + + public const uint FLASHW_TRAY = 2u; + + public const uint FLASHW_ALL = 3u; + + public const uint FLASHW_TIMER = 4u; + + public const uint FLASHW_TIMERNOFG = 12u; + + private static bool Win2000OrLater => Environment.OSVersion.Version.Major >= 5; + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool FlashWindowEx(ref FLASHWINFO pwfi); + + [DllImport("user32.dll")] + private static extern IntPtr GetActiveWindow(); + + [DllImport("user32.dll")] + private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); + + [DllImport("user32.dll")] + private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId); + + [DllImport("kernel32.dll")] + private static extern IntPtr GetCurrentProcessId(); + + private static bool GetWindowEnum(IntPtr hWnd, IntPtr lParam) + { + GetWindowThreadProcessId(hWnd, out var lpdwProcessId); + if (lpdwProcessId == myProcessId) + { + myWindow = hWnd; + return false; + } + return true; + } + + private static void UpdateCurrentWindow() + { + EnumWindows(GetWindowEnum, IntPtr.Zero); + } + + private static bool IsCurrentWindowValid() + { + GetWindowThreadProcessId(myWindow, out var lpdwProcessId); + if (lpdwProcessId != myProcessId) + { + myWindow = IntPtr.Zero; + } + return myWindow != IntPtr.Zero; + } + + public static IntPtr GetWindowHandle() + { + if (!IsCurrentWindowValid()) + { + UpdateCurrentWindow(); + } + return myWindow; + } + + public static bool Flash(IntPtr formHandle) + { + if (Win2000OrLater) + { + FLASHWINFO pwfi = Create_FLASHWINFO(formHandle, 15u, uint.MaxValue, 0u); + return FlashWindowEx(ref pwfi); + } + return false; + } + + private static FLASHWINFO Create_FLASHWINFO(IntPtr handle, uint flags, uint count, uint timeout) + { + FLASHWINFO fLASHWINFO = default(FLASHWINFO); + fLASHWINFO.cbSize = Convert.ToUInt32(Marshal.SizeOf(fLASHWINFO)); + fLASHWINFO.hwnd = handle; + fLASHWINFO.dwFlags = flags; + fLASHWINFO.uCount = count; + fLASHWINFO.dwTimeout = timeout; + return fLASHWINFO; + } + + public static bool Flash(IntPtr formHandle, uint count) + { + if (Win2000OrLater) + { + FLASHWINFO pwfi = Create_FLASHWINFO(formHandle, 3u, count, 0u); + return FlashWindowEx(ref pwfi); + } + return false; + } + + public static bool Flash() + { + return Flash(GetWindowHandle()); + } + + public static bool Start(IntPtr formHandle) + { + if (Win2000OrLater) + { + FLASHWINFO pwfi = Create_FLASHWINFO(formHandle, 3u, uint.MaxValue, 0u); + return FlashWindowEx(ref pwfi); + } + return false; + } + + public static bool Stop(IntPtr formHandle) + { + if (Win2000OrLater) + { + FLASHWINFO pwfi = Create_FLASHWINFO(formHandle, 0u, uint.MaxValue, 0u); + return FlashWindowEx(ref pwfi); + } + return false; + } + + [InitDuringStartup] + private static void Init() + { + SceneManager.activeSceneChanged += delegate(Scene previousScene, Scene newScene) + { + if (newScene.name == "lobby") + { + Flash(); + } + }; + NetworkManagerSystem.onClientConnectGlobal += delegate + { + Flash(); + }; + } +} diff --git a/ilspy_dump/ror2_csproj/FloatPID.cs b/ilspy_dump/ror2_csproj/FloatPID.cs new file mode 100644 index 0000000..b65fceb --- /dev/null +++ b/ilspy_dump/ror2_csproj/FloatPID.cs @@ -0,0 +1,60 @@ +using UnityEngine; + +public class FloatPID : MonoBehaviour +{ + [Tooltip("PID Constants.")] + public Vector3 PID = new Vector3(1f, 0f, 0f); + + public float gain = 1f; + + [Tooltip("The value we are currently at.")] + [HideInInspector] + public float inputFloat; + + [HideInInspector] + [Tooltip("The value we want to be at.")] + public float targetFloat; + + [Tooltip("Value output from PID controller; what we read.")] + [HideInInspector] + public float outputFloat; + + public float timeBetweenUpdates; + + private float timer; + + private float errorSum; + + private float deltaError; + + private float lastError; + + private float lastTimer; + + public bool automaticallyUpdate; + + private void Start() + { + } + + private void FixedUpdate() + { + timer += Time.fixedDeltaTime; + if (automaticallyUpdate && timer > timeBetweenUpdates) + { + timer -= timeBetweenUpdates; + outputFloat = UpdatePID(); + } + } + + public float UpdatePID() + { + float num = timer - lastTimer; + lastTimer = timer; + float num2 = targetFloat - inputFloat; + errorSum += num2 * num; + deltaError = (num2 - lastError) / num; + lastError = num2; + return (num2 * PID.x + errorSum * PID.y + deltaError * PID.z) * gain; + } +} diff --git a/ilspy_dump/ror2_csproj/FocusedConvergenceAnimator.cs b/ilspy_dump/ror2_csproj/FocusedConvergenceAnimator.cs new file mode 100644 index 0000000..78b5480 --- /dev/null +++ b/ilspy_dump/ror2_csproj/FocusedConvergenceAnimator.cs @@ -0,0 +1,119 @@ +using UnityEngine; + +public class FocusedConvergenceAnimator : MonoBehaviour +{ + public bool animateX; + + public bool animateY; + + public bool animateZ; + + private AnimationCurve animCurve; + + private float xScale; + + private float yScale; + + private float zScale; + + public float scaleTime = 4f; + + private float tempScaleTimer = 4f; + + public float rotateTime = 4f; + + private float tempRotateTimer = 4f; + + private float scaleMax = 1.2f; + + private float scaleMin = 0.8f; + + private bool isScaling; + + private float xRotate; + + private float xRotateTop; + + private float yRotate; + + private float yRotateTop; + + private float zRotate; + + private float zRotateTop; + + private void Start() + { + tempScaleTimer = 0f; + tempRotateTimer = 0f; + animCurve = AnimationCurve.EaseInOut(0f, scaleMin, 1f, scaleMax); + } + + private void FixedUpdate() + { + if (isScaling) + { + tempScaleTimer += Time.deltaTime; + if (tempScaleTimer <= scaleTime * 0.333f) + { + float t = tempScaleTimer / (scaleTime * 0.333f); + xScale = Mathf.Lerp(1f, scaleMax, t); + yScale = Mathf.Lerp(1f, scaleMax, t); + zScale = Mathf.Lerp(1f, scaleMax, t); + } + if (tempScaleTimer > scaleTime * 0.333f && tempScaleTimer <= scaleTime * 0.666f) + { + float t = (tempScaleTimer - scaleTime * 0.333f) / (scaleTime * 0.333f); + xScale = Mathf.Lerp(scaleMax, scaleMin, t); + yScale = Mathf.Lerp(scaleMax, scaleMin, t); + zScale = Mathf.Lerp(scaleMax, scaleMin, t); + } + if (tempScaleTimer > scaleTime * 0.666f) + { + float t = (tempScaleTimer - scaleTime * 0.666f) / (scaleTime * 0.333f); + xScale = Mathf.Lerp(scaleMin, 1f, t); + yScale = Mathf.Lerp(scaleMin, 1f, t); + zScale = Mathf.Lerp(scaleMin, 1f, t); + } + if (tempScaleTimer >= scaleTime) + { + isScaling = false; + tempRotateTimer = 0f; + xRotateTop = Random.Range(0f, 10f); + yRotateTop = Random.Range(0f, 10f); + zRotateTop = Random.Range(0f, 10f); + } + else + { + base.transform.localScale = new Vector3(xScale, yScale, zScale); + } + } + else + { + tempRotateTimer += Time.deltaTime; + if (tempRotateTimer <= rotateTime * 0.5f) + { + float t2 = tempRotateTimer / (rotateTime * 0.5f); + xRotate = Mathf.Lerp(0f, xRotateTop, t2); + yRotate = Mathf.Lerp(0f, yRotateTop, t2); + zRotate = Mathf.Lerp(0f, zRotateTop, t2); + } + else + { + float t2 = (tempRotateTimer - rotateTime * 0.5f) / (rotateTime * 0.5f); + xRotate = Mathf.Lerp(xRotateTop, 0f, t2); + yRotate = Mathf.Lerp(yRotateTop, 0f, t2); + zRotate = Mathf.Lerp(zRotateTop, 0f, t2); + } + if (tempRotateTimer >= rotateTime) + { + isScaling = true; + tempScaleTimer = 0f; + } + else + { + base.transform.Rotate(new Vector3(xRotate, yRotate, zRotate)); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/ForcePose.cs b/ilspy_dump/ror2_csproj/ForcePose.cs new file mode 100644 index 0000000..d365872 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ForcePose.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +[RequireComponent(typeof(Animator))] +[ExecuteInEditMode] +public class ForcePose : MonoBehaviour +{ + [Tooltip("The animation clip to force.")] + public AnimationClip clip; + + [Tooltip("The moment in the cycle to force.")] + [Range(0f, 1f)] + public float cycle; + + private void Start() + { + } + + private void Update() + { + if ((bool)clip) + { + clip.SampleAnimation(base.gameObject, cycle * clip.length); + } + } +} diff --git a/ilspy_dump/ror2_csproj/FriendSessionBrowserController.cs b/ilspy_dump/ror2_csproj/FriendSessionBrowserController.cs new file mode 100644 index 0000000..ba7a926 --- /dev/null +++ b/ilspy_dump/ror2_csproj/FriendSessionBrowserController.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using RoR2.UI; +using TMPro; +using UnityEngine; + +public class FriendSessionBrowserController : MonoBehaviour +{ + public SessionButtonController SessionButtonPrefab; + + public Transform SessionButtonContainer; + + public RectTransform InProgressSpinner; + + public TextMeshProUGUI SearchStateText; + + public MPButton RefreshButton; + + public MPButton BackButton; + + private List sessionButtons; +} diff --git a/ilspy_dump/ror2_csproj/GamecoreLeaderboards.cs b/ilspy_dump/ror2_csproj/GamecoreLeaderboards.cs new file mode 100644 index 0000000..1c3c882 --- /dev/null +++ b/ilspy_dump/ror2_csproj/GamecoreLeaderboards.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class GamecoreLeaderboards : MonoBehaviour +{ +} diff --git a/ilspy_dump/ror2_csproj/GamecoreNameDisplay.cs b/ilspy_dump/ror2_csproj/GamecoreNameDisplay.cs new file mode 100644 index 0000000..72c7589 --- /dev/null +++ b/ilspy_dump/ror2_csproj/GamecoreNameDisplay.cs @@ -0,0 +1,14 @@ +using RoR2.UI; +using UnityEngine; + +public class GamecoreNameDisplay : MonoBehaviour +{ + public HGTextMeshProUGUI Text; + + public GameObject Parent; + + private void Awake() + { + Parent.SetActive(value: false); + } +} diff --git a/ilspy_dump/ror2_csproj/GamecoreSwitchUser.cs b/ilspy_dump/ror2_csproj/GamecoreSwitchUser.cs new file mode 100644 index 0000000..aebb9f2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/GamecoreSwitchUser.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class GamecoreSwitchUser : MonoBehaviour +{ + public void OnButtonClick() + { + } +} diff --git a/ilspy_dump/ror2_csproj/GenericInspectInfoProvider.cs b/ilspy_dump/ror2_csproj/GenericInspectInfoProvider.cs new file mode 100644 index 0000000..1dbbfa6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/GenericInspectInfoProvider.cs @@ -0,0 +1,32 @@ +using RoR2; +using RoR2.UI; +using UnityEngine; + +public class GenericInspectInfoProvider : MonoBehaviour, IInspectInfoProvider, IHasInspectHintOverride +{ + public InspectDef InspectInfo; + + [Tooltip("Set this to a non-empty token to override the default Inspect hint on the HUD.")] + public string inspectHintOverrideToken; + + public bool CanBeInspected() + { + return true; + } + + public InspectInfo GetInfo() + { + return InspectInfo; + } + + public bool GetInspectHintOverride(out string hintOverride) + { + if (inspectHintOverrideToken.Length > 0) + { + hintOverride = Language.GetString(inspectHintOverrideToken); + return true; + } + hintOverride = null; + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/GlobalPrefabFunctions.cs b/ilspy_dump/ror2_csproj/GlobalPrefabFunctions.cs new file mode 100644 index 0000000..b76ec39 --- /dev/null +++ b/ilspy_dump/ror2_csproj/GlobalPrefabFunctions.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public static class GlobalPrefabFunctions +{ + private static bool doSave = true; + + private static Transform FindRecursive(Transform t, string name) + { + if (t.name == name) + { + return t; + } + for (int i = 0; i < t.childCount; i++) + { + Transform child = t.GetChild(i); + child = FindRecursive(child, name); + if (child != null) + { + return child; + } + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/GlobalShaderTextures.cs b/ilspy_dump/ror2_csproj/GlobalShaderTextures.cs new file mode 100644 index 0000000..f0f686e --- /dev/null +++ b/ilspy_dump/ror2_csproj/GlobalShaderTextures.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +[ExecuteInEditMode] +public class GlobalShaderTextures : MonoBehaviour +{ + public Texture warpRampTexture; + + public string warpRampShaderVariableName; + + public Texture eliteRampTexture; + + public string eliteRampShaderVariableName; + + public Texture snowMicrofacetTexture; + + public string snowMicrofacetNoiseVariableName; + + private void OnValidate() + { + Shader.SetGlobalTexture(warpRampShaderVariableName, warpRampTexture); + Shader.SetGlobalTexture(eliteRampShaderVariableName, eliteRampTexture); + Shader.SetGlobalTexture(snowMicrofacetNoiseVariableName, snowMicrofacetTexture); + } + + private void Start() + { + Shader.SetGlobalTexture(warpRampShaderVariableName, warpRampTexture); + Shader.SetGlobalTexture(eliteRampShaderVariableName, eliteRampTexture); + Shader.SetGlobalTexture(snowMicrofacetNoiseVariableName, snowMicrofacetTexture); + } +} diff --git a/ilspy_dump/ror2_csproj/GrandparentEnergyFXController.cs b/ilspy_dump/ror2_csproj/GrandparentEnergyFXController.cs new file mode 100644 index 0000000..47d7f0f --- /dev/null +++ b/ilspy_dump/ror2_csproj/GrandparentEnergyFXController.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using RoR2; +using UnityEngine; + +public class GrandparentEnergyFXController : MonoBehaviour +{ + public List energyFXParticles = new List(); + + [HideInInspector] + public GameObject portalObject; + + private bool isPortalSoundPlaying; + + private void Start() + { + } + + private void FixedUpdate() + { + if (!(portalObject != null)) + { + return; + } + if (!isPortalSoundPlaying) + { + if (portalObject.transform.localScale == Vector3.zero) + { + Util.PlaySound("Play_grandparent_portal_loop", portalObject); + isPortalSoundPlaying = false; + } + } + else if (portalObject.transform.localScale != Vector3.zero) + { + Util.PlaySound("Stop_grandparent_portal_loop", portalObject); + isPortalSoundPlaying = true; + } + } + + public void TurnOffFX() + { + for (int i = 0; i < energyFXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = energyFXParticles[i].emission; + emission.enabled = false; + } + if (portalObject != null) + { + ParticleSystem componentInChildren = portalObject.GetComponentInChildren(); + if (componentInChildren != null) + { + ParticleSystem.EmissionModule emission2 = componentInChildren.emission; + emission2.enabled = false; + } + } + } + + public void TurnOnFX() + { + for (int i = 0; i < energyFXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = energyFXParticles[i].emission; + emission.enabled = true; + } + if (portalObject != null) + { + ParticleSystem componentInChildren = portalObject.GetComponentInChildren(); + if (componentInChildren != null) + { + ParticleSystem.EmissionModule emission2 = componentInChildren.emission; + emission2.enabled = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/HGArrayUtilities.cs b/ilspy_dump/ror2_csproj/HGArrayUtilities.cs new file mode 100644 index 0000000..a893f22 --- /dev/null +++ b/ilspy_dump/ror2_csproj/HGArrayUtilities.cs @@ -0,0 +1,110 @@ +using System; +using System.Runtime.CompilerServices; +using HG; +using JetBrains.Annotations; + +[Obsolete("HGArrayUtilities is deprecated. Use HG.ArrayUtils instead.")] +public static class HGArrayUtilities +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayInsertNoResize(T[] array, int arraySize, int position, ref T value) + { + ArrayUtils.ArrayInsertNoResize(array, arraySize, position, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayInsert(ref T[] array, ref int arraySize, int position, ref T value) + { + ArrayUtils.ArrayInsert(ref array, ref arraySize, position, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayInsert(ref T[] array, int position, ref T value) + { + ArrayUtils.ArrayInsert(ref array, position, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayAppend(ref T[] array, ref int arraySize, ref T value) + { + ArrayUtils.ArrayAppend(ref array, ref arraySize, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayAppend(ref T[] array, ref T value) + { + ArrayUtils.ArrayAppend(ref array, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayRemoveAt(ref T[] array, ref int arraySize, int position, int count = 1) + { + ArrayUtils.ArrayRemoveAt(array, ref arraySize, position, count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ArrayRemoveAtAndResize(ref T[] array, int position, int count = 1) + { + ArrayUtils.ArrayRemoveAtAndResize(ref array, position, count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T GetSafe([NotNull] T[] array, int index) + { + return ArrayUtils.GetSafe(array, index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T GetSafe([NotNull] T[] array, int index, T defaultValue) + { + return ArrayUtils.GetSafe(array, index, in defaultValue); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SetAll(T[] array, in T value) + { + ArrayUtils.SetAll(array, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void EnsureCapacity(ref T[] array, int capacity) + { + ArrayUtils.EnsureCapacity(ref array, capacity); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Swap(T[] array, int a, int b) + { + ArrayUtils.Swap(array, a, b); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clear(T[] array, ref int count) + { + ArrayUtils.Clear(array, ref count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool SequenceEquals(T[] a, T[] b) where T : IEquatable + { + return ArrayUtils.SequenceEquals(a, b); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T[] Clone(T[] src) + { + return ArrayUtils.Clone(src); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsInBounds(T[] array, int index) + { + return ArrayUtils.IsInBounds(array, index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsInBounds(T[] array, uint index) + { + return ArrayUtils.IsInBounds(array, index); + } +} diff --git a/ilspy_dump/ror2_csproj/HGMath.cs b/ilspy_dump/ror2_csproj/HGMath.cs new file mode 100644 index 0000000..d09d0fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/HGMath.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using HG; +using UnityEngine; + +public static class HGMath +{ + [Obsolete("Use HG.Vector3Utils.AverageFast or .AveragePrecise instead.", false)] + public static Vector3 Average(T entries) where T : ICollection + { + int count = entries.Count; + float num = 1f / (float)count; + Vector3 zero = Vector3.zero; + foreach (Vector3 item in entries) + { + zero += num * item; + } + return zero; + } + + [Obsolete("Use HG.Vector3Utils.Average instead.", false)] + public static Vector3 Average(in Vector3 a, in Vector3 b) + { + return Vector3Utils.Average(in a, in b); + } + + [Obsolete("Use HG.Vector3Utils.Average instead.", false)] + public static Vector3 Average(in Vector3 a, in Vector3 b, in Vector3 c) + { + return Vector3Utils.Average(in a, in b, in c); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IntDivCeil(int a, int b) + { + return (a - 1) / b + 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint UintSafeSubtract(uint a, uint b) + { + if (b <= a) + { + return a - b; + } + return 0u; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint UintSafeAdd(uint a, uint b) + { + uint num = a + b; + uint num2 = ((a > b) ? a : b); + if (num >= num2) + { + return num; + } + return uint.MaxValue; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte ByteSafeSubtract(byte a, byte b) + { + if (b <= a) + { + return (byte)(a - b); + } + return 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte ByteSafeAdd(byte a, byte b) + { + byte b2 = (byte)(a + b); + byte b3 = ((a > b) ? a : b); + if (b2 >= b3) + { + return b2; + } + return byte.MaxValue; + } + + public static Vector3 Remap(Vector3 value, Vector3 inMin, Vector3 inMax, Vector3 outMin, Vector3 outMax) + { + return new Vector3(outMin.x + (value.x - inMin.x) / (inMax.x - inMin.x) * (outMax.x - outMin.x), outMin.y + (value.y - inMin.y) / (inMax.y - inMin.y) * (outMax.y - outMin.y), outMin.z + (value.z - inMin.z) / (inMax.z - inMin.z) * (outMax.z - outMin.z)); + } + + public static Vector3 Remap(Vector3 value, float inMin, float inMax, float outMin, float outMax) + { + return new Vector3(outMin + (value.x - inMin) / (inMax - inMin) * (outMax - outMin), outMin + (value.y - inMin) / (inMax - inMin) * (outMax - outMin), outMin + (value.z - inMin) / (inMax - inMin) * (outMax - outMin)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float Clamp(float value, float min, float max) + { + if (!(value > min)) + { + return min; + } + if (!(value < max)) + { + return max; + } + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Clamp(int value, int min, int max) + { + if (value <= min) + { + return min; + } + if (value >= max) + { + return max; + } + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint Clamp(uint value, uint min, uint max) + { + if (value <= min) + { + return min; + } + if (value >= max) + { + return max; + } + return value; + } + + public static Vector3 Clamp(Vector3 value, Vector3 min, Vector3 max) + { + return new Vector3(Clamp(value.x, min.x, max.x), Clamp(value.y, min.y, max.y), Clamp(value.z, min.z, max.z)); + } + + public static Vector3 Clamp(Vector3 value, float min, float max) + { + return new Vector3(Clamp(value.x, min, max), Clamp(value.y, min, max), Clamp(value.z, min, max)); + } + + public static bool IsVectorNaN(Vector3 value) + { + if (!float.IsNaN(value.x) && !float.IsNaN(value.y)) + { + return float.IsNaN(value.z); + } + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsVectorValid(ref Vector3 vector3) + { + float f = vector3.x + vector3.y + vector3.z; + if (!float.IsInfinity(f)) + { + return !float.IsNaN(f); + } + return false; + } + + public static bool Overshoots(Vector3 startPosition, Vector3 endPosition, Vector3 targetPosition) + { + Vector3 lhs = endPosition - startPosition; + Vector3 rhs = targetPosition - endPosition; + return Vector3.Dot(lhs, rhs) <= 0f; + } + + public static float TriangleArea(in Vector3 a, in Vector3 b, in Vector3 c) + { + return 0.5f * Vector3.Cross(b - a, c - a).magnitude; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float CircleRadiusToArea(float radius) + { + return MathF.PI * (radius * radius); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float CircleAreaToRadius(float area) + { + return Mathf.Sqrt(area * (1f / MathF.PI)); + } +} diff --git a/ilspy_dump/ror2_csproj/HGUnitConversions.cs b/ilspy_dump/ror2_csproj/HGUnitConversions.cs new file mode 100644 index 0000000..2751ca2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/HGUnitConversions.cs @@ -0,0 +1,14 @@ +public static class HGUnitConversions +{ + public static readonly double milesToKilometers = 1.609344; + + public static readonly double kilometersToMeters = 1000.0; + + public static readonly double milesToMeters = milesToKilometers * kilometersToMeters; + + public static readonly double hoursToMinutes = 60.0; + + public static readonly double minutesToSeconds = 60.0; + + public static readonly double hoursToSeconds = hoursToMinutes * minutesToSeconds; +} diff --git a/ilspy_dump/ror2_csproj/HGXml.cs b/ilspy_dump/ror2_csproj/HGXml.cs new file mode 100644 index 0000000..6041ed0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/HGXml.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using JetBrains.Annotations; +using UnityEngine; + +public static class HGXml +{ + public delegate void Serializer(XElement element, T contents); + + public delegate bool Deserializer(XElement element, ref T contents); + + public class SerializationRules + { + public Serializer serializer; + + public Deserializer deserializer; + + public static SerializationRules defaultRules; + + static SerializationRules() + { + if (typeof(T).IsEnum) + { + RegisterEnum(); + } + } + + private static void RegisterEnum() + { + Type typeFromHandle = typeof(T); + Dictionary nameToValue = new Dictionary(); + string[] names = Enum.GetNames(typeFromHandle); + for (int i = 0; i < names.Length; i++) + { + string text = names[i]; + Enum.Parse(typeFromHandle, names[i]); + nameToValue[text] = (T)Enum.Parse(typeFromHandle, text); + } + Dictionary valueToName = new Dictionary(); + Array values = Enum.GetValues(typeFromHandle); + for (int j = 0; j < values.Length; j++) + { + object value = values.GetValue(j); + valueToName[(T)value] = Enum.GetName(typeFromHandle, value); + } + defaultRules = new SerializationRules + { + serializer = Serializer, + deserializer = Deserializer + }; + bool Deserializer(XElement element, ref T contents) + { + if (nameToValue.TryGetValue(element.Value, out var value2)) + { + contents = value2; + return true; + } + try + { + contents = (T)Enum.Parse(typeof(T), element.Value); + return true; + } + catch (Exception) + { + } + return false; + } + void Serializer(XElement element, T contents) + { + if (valueToName.TryGetValue(contents, out var value3)) + { + element.Value = value3; + } + else + { + element.Value = contents.ToString(); + } + } + } + } + + public static void Register(Serializer serializer, Deserializer deserializer) + { + SerializationRules.defaultRules = new SerializationRules + { + serializer = serializer, + deserializer = deserializer + }; + } + + [NotNull] + public static XElement ToXml(string name, T value) + { + return ToXml(name, value, SerializationRules.defaultRules); + } + + [NotNull] + public static XElement ToXml(string name, T value, SerializationRules rules) + { + XElement xElement = new XElement(name); + rules.serializer(xElement, value); + return xElement; + } + + public static bool FromXml([NotNull] XElement element, ref T value) + { + return FromXml(element, ref value, SerializationRules.defaultRules); + } + + public static bool FromXml([NotNull] XElement element, ref T value, SerializationRules rules) + { + if (rules == null) + { + Debug.LogFormat("Serialization rules not defined for type <{0}>", typeof(T).Name); + return false; + } + return rules.deserializer(element, ref value); + } + + public static bool FromXml([NotNull] XElement element, [NotNull] Action setter) + { + return FromXml(element, setter, SerializationRules.defaultRules); + } + + public static bool FromXml([NotNull] XElement element, [NotNull] Action setter, [NotNull] SerializationRules rules) + { + T value = default(T); + if (FromXml(element, ref value, rules)) + { + setter(value); + return true; + } + return false; + } + + static HGXml() + { + Register(delegate(XElement element, int contents) + { + element.Value = TextSerialization.ToStringInvariant(contents); + }, delegate(XElement element, ref int contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out int result8)) + { + contents = result8; + return true; + } + return false; + }); + Register(delegate(XElement element, uint contents) + { + element.Value = TextSerialization.ToStringInvariant(contents); + }, delegate(XElement element, ref uint contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out uint result7)) + { + contents = result7; + return true; + } + return false; + }); + Register(delegate(XElement element, ulong contents) + { + element.Value = TextSerialization.ToStringInvariant(contents); + }, delegate(XElement element, ref ulong contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out ulong result6)) + { + contents = result6; + return true; + } + return false; + }); + Register(delegate(XElement element, bool contents) + { + element.Value = (contents ? "1" : "0"); + }, delegate(XElement element, ref bool contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out int result5)) + { + contents = result5 != 0; + return true; + } + return false; + }); + Register(delegate(XElement element, float contents) + { + element.Value = TextSerialization.ToStringInvariant(contents); + }, delegate(XElement element, ref float contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out float result4)) + { + contents = result4; + return true; + } + return false; + }); + Register(delegate(XElement element, double contents) + { + element.Value = TextSerialization.ToStringInvariant(contents); + }, delegate(XElement element, ref double contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out double result3)) + { + contents = result3; + return true; + } + return false; + }); + Register(delegate(XElement element, string contents) + { + element.Value = contents; + }, delegate(XElement element, ref string contents) + { + contents = element.Value; + return true; + }); + Register(delegate(XElement element, Guid contents) + { + element.Value = contents.ToString(); + }, delegate(XElement element, ref Guid contents) + { + if (Guid.TryParse(element.Value, out var result2)) + { + contents = result2; + return true; + } + return false; + }); + Register(delegate(XElement element, DateTime contents) + { + element.Value = TextSerialization.ToStringInvariant(contents.ToBinary()); + }, delegate(XElement element, ref DateTime contents) + { + if (TextSerialization.TryParseInvariant(element.Value, out long result)) + { + try + { + contents = DateTime.FromBinary(result); + return true; + } + catch (ArgumentException) + { + } + } + return false; + }); + } + + public static void Deserialize(this XElement element, ref T dest) + { + FromXml(element, ref dest); + } + + public static void Deserialize(this XElement element, ref T dest, SerializationRules rules) + { + FromXml(element, ref dest, rules); + } + + public static void UsedOnlyForAOTCodeGeneration() + { + throw new InvalidOperationException("This method is used for AOT code generation only. Do not call it at runtime."); + } +} diff --git a/ilspy_dump/ror2_csproj/HereticInitialStateHelper.cs b/ilspy_dump/ror2_csproj/HereticInitialStateHelper.cs new file mode 100644 index 0000000..daa9f02 --- /dev/null +++ b/ilspy_dump/ror2_csproj/HereticInitialStateHelper.cs @@ -0,0 +1,15 @@ +using EntityStates; +using EntityStates.Heretic; +using RoR2; +using UnityEngine; + +public class HereticInitialStateHelper : MonoBehaviour +{ + [SerializeField] + private EntityStateMachine entityStateMachine; + + public void PrepareTransformation() + { + entityStateMachine.initialStateType = new SerializableEntityStateType(typeof(SpawnState)); + } +} diff --git a/ilspy_dump/ror2_csproj/HideIfSurvivorLocked.cs b/ilspy_dump/ror2_csproj/HideIfSurvivorLocked.cs new file mode 100644 index 0000000..af52e12 --- /dev/null +++ b/ilspy_dump/ror2_csproj/HideIfSurvivorLocked.cs @@ -0,0 +1,53 @@ +using System.Linq; +using RoR2; +using RoR2.EntitlementManagement; +using UnityEngine; + +public class HideIfSurvivorLocked : MonoBehaviour +{ + [Tooltip("Survivor Def(s) that must be unlocked in order to show this component's gameObject. (ANY)")] + public SurvivorDef[] requiredSurvivors; + + [Tooltip("Indicator to show that none of the designated survivors are unlocked.")] + public GameObject lockedIndicator; + + private void Awake() + { + EntitlementManager.onEntitlementsUpdated += Reset; + Reset(); + } + + private void OnDestroy() + { + EntitlementManager.onEntitlementsUpdated -= Reset; + } + + private void Reset() + { + if (requiredSurvivors.Length != 0) + { + if (requiredSurvivors.Any((SurvivorDef survivorDef) => SurvivorCatalog.SurvivorIsUnlockedOnThisClient(survivorDef.survivorIndex) && survivorDef.CheckLocalUserHasRequiredEntitlement())) + { + base.gameObject.SetActive(value: true); + SetLockIndicator(value: false); + } + else + { + base.gameObject.SetActive(value: false); + SetLockIndicator(value: true); + } + } + else + { + Debug.LogWarning("No designated requiredSurvivors or lockedIndicator on HideIfSurvivorLocked. Consider updating or removing this component on gameObject:" + base.gameObject.name + "."); + } + } + + private void SetLockIndicator(bool value) + { + if (lockedIndicator != null) + { + lockedIndicator.SetActive(value); + } + } +} diff --git a/ilspy_dump/ror2_csproj/HoverOverHead.cs b/ilspy_dump/ror2_csproj/HoverOverHead.cs new file mode 100644 index 0000000..98fb2ac --- /dev/null +++ b/ilspy_dump/ror2_csproj/HoverOverHead.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +public class HoverOverHead : MonoBehaviour +{ + private Transform parentTransform; + + private Collider bodyCollider; + + public Vector3 bonusOffset; + + private void Start() + { + Reset(); + } + + public void Reset() + { + if ((bool)base.transform) + { + parentTransform = base.transform.parent; + bodyCollider = ((parentTransform == null) ? null : parentTransform.GetComponent()); + } + } + + private void Update() + { + if ((bool)parentTransform) + { + Vector3 vector = parentTransform.position; + if ((bool)bodyCollider) + { + vector = bodyCollider.bounds.center + new Vector3(0f, bodyCollider.bounds.extents.y, 0f); + } + base.transform.position = vector + bonusOffset; + } + } +} diff --git a/ilspy_dump/ror2_csproj/IToStringImplementation.cs b/ilspy_dump/ror2_csproj/IToStringImplementation.cs new file mode 100644 index 0000000..ff5590c --- /dev/null +++ b/ilspy_dump/ror2_csproj/IToStringImplementation.cs @@ -0,0 +1,4 @@ +public interface IToStringImplementation +{ + string DoToString(in T input); +} diff --git a/ilspy_dump/ror2_csproj/InterpolatedTransform.cs b/ilspy_dump/ror2_csproj/InterpolatedTransform.cs new file mode 100644 index 0000000..74f5ceb --- /dev/null +++ b/ilspy_dump/ror2_csproj/InterpolatedTransform.cs @@ -0,0 +1,78 @@ +using RoR2; +using UnityEngine; +using UnityEngine.EventSystems; + +[RequireComponent(typeof(InterpolatedTransformUpdater))] +public class InterpolatedTransform : MonoBehaviour, ITeleportHandler, IEventSystemHandler +{ + private struct TransformData + { + public Vector3 position; + + public Quaternion rotation; + + public Vector3 scale; + + public TransformData(Vector3 position, Quaternion rotation, Vector3 scale) + { + this.position = position; + this.rotation = rotation; + this.scale = scale; + } + } + + private TransformData[] m_lastTransforms; + + private int m_newTransformIndex; + + private void OnEnable() + { + ForgetPreviousTransforms(); + } + + public void ForgetPreviousTransforms() + { + m_lastTransforms = new TransformData[2]; + TransformData transformData = new TransformData(base.transform.localPosition, base.transform.localRotation, base.transform.localScale); + m_lastTransforms[0] = transformData; + m_lastTransforms[1] = transformData; + m_newTransformIndex = 0; + } + + private void FixedUpdate() + { + TransformData transformData = m_lastTransforms[m_newTransformIndex]; + base.transform.localPosition = transformData.position; + base.transform.localRotation = transformData.rotation; + base.transform.localScale = transformData.scale; + } + + public void LateFixedUpdate() + { + m_newTransformIndex = OldTransformIndex(); + m_lastTransforms[m_newTransformIndex] = new TransformData(base.transform.localPosition, base.transform.localRotation, base.transform.localScale); + } + + private void Update() + { + TransformData transformData = m_lastTransforms[m_newTransformIndex]; + TransformData transformData2 = m_lastTransforms[OldTransformIndex()]; + base.transform.localPosition = Vector3.Lerp(transformData2.position, transformData.position, InterpolationController.InterpolationFactor); + base.transform.localRotation = Quaternion.Slerp(transformData2.rotation, transformData.rotation, InterpolationController.InterpolationFactor); + base.transform.localScale = Vector3.Lerp(transformData2.scale, transformData.scale, InterpolationController.InterpolationFactor); + } + + private int OldTransformIndex() + { + if (m_newTransformIndex != 0) + { + return 0; + } + return 1; + } + + public void OnTeleport(Vector3 oldPosition, Vector3 newPosition) + { + ForgetPreviousTransforms(); + } +} diff --git a/ilspy_dump/ror2_csproj/InterpolatedTransformUpdater.cs b/ilspy_dump/ror2_csproj/InterpolatedTransformUpdater.cs new file mode 100644 index 0000000..c1f8300 --- /dev/null +++ b/ilspy_dump/ror2_csproj/InterpolatedTransformUpdater.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class InterpolatedTransformUpdater : MonoBehaviour +{ + private InterpolatedTransform m_interpolatedTransform; + + private void Awake() + { + m_interpolatedTransform = GetComponent(); + } + + private void FixedUpdate() + { + m_interpolatedTransform.LateFixedUpdate(); + } +} diff --git a/ilspy_dump/ror2_csproj/InterpolationController.cs b/ilspy_dump/ror2_csproj/InterpolationController.cs new file mode 100644 index 0000000..4b0a276 --- /dev/null +++ b/ilspy_dump/ror2_csproj/InterpolationController.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +public class InterpolationController : MonoBehaviour +{ + private float[] m_lastFixedUpdateTimes; + + private int m_newTimeIndex; + + private static float m_interpolationFactor; + + public static float InterpolationFactor => m_interpolationFactor; + + public void Start() + { + m_lastFixedUpdateTimes = new float[2]; + m_newTimeIndex = 0; + } + + public void FixedUpdate() + { + m_newTimeIndex = OldTimeIndex(); + m_lastFixedUpdateTimes[m_newTimeIndex] = Time.fixedTime; + } + + public void Update() + { + float num = m_lastFixedUpdateTimes[m_newTimeIndex]; + float num2 = m_lastFixedUpdateTimes[OldTimeIndex()]; + if (num != num2) + { + m_interpolationFactor = (Time.time - num) / (num - num2); + } + else + { + m_interpolationFactor = 1f; + } + } + + private int OldTimeIndex() + { + if (m_newTimeIndex != 0) + { + return 0; + } + return 1; + } +} diff --git a/ilspy_dump/ror2_csproj/InviteButton.cs b/ilspy_dump/ror2_csproj/InviteButton.cs new file mode 100644 index 0000000..423dd01 --- /dev/null +++ b/ilspy_dump/ror2_csproj/InviteButton.cs @@ -0,0 +1,10 @@ +using RoR2; +using UnityEngine; + +public class InviteButton : MonoBehaviour +{ + public void OnInviteButtonPressed() + { + PlatformSystems.lobbyManager.OpenInviteOverlay(); + } +} diff --git a/ilspy_dump/ror2_csproj/ItemIndexStorage.cs b/ilspy_dump/ror2_csproj/ItemIndexStorage.cs new file mode 100644 index 0000000..e58658c --- /dev/null +++ b/ilspy_dump/ror2_csproj/ItemIndexStorage.cs @@ -0,0 +1,11 @@ +using RoR2; +using UnityEngine; + +public class ItemIndexStorage : MonoBehaviour +{ + public bool isEquipment; + + public ItemIndex itemIndex; + + public EquipmentIndex equipmentIndex; +} diff --git a/ilspy_dump/ror2_csproj/JobCleaner.cs b/ilspy_dump/ror2_csproj/JobCleaner.cs new file mode 100644 index 0000000..98c931c --- /dev/null +++ b/ilspy_dump/ror2_csproj/JobCleaner.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using UnityEngine; + +public class JobCleaner : MonoBehaviour +{ + public static JobCleaner instance; + + public List jobsToClean; + + private void Awake() + { + if (instance == null) + { + instance = this; + } + jobsToClean = new List(); + } + + private void OnDestroy() + { + if (instance == this) + { + instance = null; + } + if (jobsToClean.Count <= 0) + { + return; + } + Debug.LogError("JOBCLEANER HAS JOBS TO CLEAN BEFORE BEING DESTROYED"); + while (jobsToClean.Count > 0) + { + for (int num = jobsToClean.Count - 1; num >= 0; num--) + { + if (jobsToClean[num].handle.IsCompleted) + { + jobsToClean[num].handle.Complete(); + jobsToClean[num].Dispose(); + jobsToClean.RemoveAt(num); + } + } + } + Debug.LogError("JOBCLEANER FINISHED CLEANING JOBS, CAN DIE HAPPY NOW"); + } + + private void LateUpdate() + { + if (jobsToClean.Count > 0) + { + int index = jobsToClean.Count - 1; + if (jobsToClean[index].handle.IsCompleted) + { + jobsToClean[index].handle.Complete(); + jobsToClean[index].Dispose(); + jobsToClean.RemoveAt(index); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/JobWrapper.cs b/ilspy_dump/ror2_csproj/JobWrapper.cs new file mode 100644 index 0000000..89b36a2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/JobWrapper.cs @@ -0,0 +1,53 @@ +using Unity.Jobs; +using UnityEngine; + +public class JobWrapper +{ + public JobHandle handle; + + public bool jobScheduled; + + public bool isComplete + { + get + { + if (jobScheduled) + { + return handle.IsCompleted; + } + return true; + } + } + + public virtual void Dispose() + { + Debug.LogError("Error: No overload for JobWrapper.Dispose()"); + } + + public virtual void Initialize(Object data) + { + Debug.LogError("Error: No overload for JobWrapper:Initialize()"); + } + + public virtual void Schedule() + { + JobHandle.ScheduleBatchedJobs(); + jobScheduled = true; + } + + public void Complete() + { + handle.Complete(); + jobScheduled = false; + } + + public bool SendToCleaner() + { + if (JobCleaner.instance != null) + { + JobCleaner.instance.jobsToClean.Add(this); + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/KeyValueSplitter.cs b/ilspy_dump/ror2_csproj/KeyValueSplitter.cs new file mode 100644 index 0000000..579d880 --- /dev/null +++ b/ilspy_dump/ror2_csproj/KeyValueSplitter.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Text; +using HG; +using JetBrains.Annotations; + +public readonly struct KeyValueSplitter +{ + private interface IStringWrapper + { + int Length { get; } + + string SubString(int startIndex, int length); + } + + private struct StringWrapper : IStringWrapper + { + private readonly string src; + + public int Length => src.Length; + + public StringWrapper([NotNull] string str) + { + src = str; + } + + public override string ToString() + { + return src; + } + + public string SubString(int startIndex, int length) + { + return src.Substring(startIndex, length); + } + } + + private struct StringBuilderWrapper : IStringWrapper + { + private readonly StringBuilder src; + + public int Length => src.Length; + + public StringBuilderWrapper([NotNull] StringBuilder src) + { + this.src = src; + } + + public override string ToString() + { + return src.ToString(); + } + + public string SubString(int startIndex, int length) + { + return src.ToString(startIndex, length); + } + } + + public readonly string baseKey; + + private readonly int maxKeyLength; + + private readonly int maxValueLength; + + private readonly List currentSubKeys; + + private readonly Action keyValueSetter; + + public KeyValueSplitter([NotNull] string baseKey, int maxKeyLength, int maxValueLength, [NotNull] Action keyValueSetter) + { + this.baseKey = baseKey; + this.maxKeyLength = maxKeyLength; + this.maxValueLength = maxValueLength; + this.keyValueSetter = keyValueSetter; + currentSubKeys = new List(); + } + + public void SetValue([NotNull] StringBuilder stringBuilder) + { + SetValueInternal(new StringBuilderWrapper(stringBuilder)); + } + + public void SetValue([NotNull] string value) + { + SetValueInternal(new StringWrapper(value)); + } + + private void SetValueInternal(T value) where T : IStringWrapper + { + int length = value.Length; + List> list = CollectionPool, List>>.RentCollection(); + if (length <= maxValueLength) + { + list.Add(new KeyValuePair(baseKey, value.ToString())); + } + else + { + int num = length; + int num2 = 0; + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + do + { + int length2 = Math.Min(num, maxValueLength); + string key = stringBuilder.Clear().Append(baseKey).Append("[") + .AppendInt(num2++) + .Append("]") + .ToString(); + string value2 = value.SubString(value.Length - num, length2); + list.Add(new KeyValuePair(key, value2)); + num -= maxValueLength; + } + while (num > 0); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } + for (int i = 0; i < currentSubKeys.Count; i++) + { + string text = currentSubKeys[i]; + bool flag = false; + for (int j = 0; j < list.Count; j++) + { + if (list[j].Key.Equals(text, StringComparison.Ordinal)) + { + flag = true; + break; + } + } + if (!flag) + { + keyValueSetter(text, null); + } + } + currentSubKeys.Clear(); + for (int k = 0; k < list.Count; k++) + { + currentSubKeys.Add(list[k].Key); + } + for (int l = 0; l < list.Count; l++) + { + KeyValuePair keyValuePair = list[l]; + keyValueSetter(keyValuePair.Key, keyValuePair.Value); + } + CollectionPool, List>>.ReturnCollection(list); + } +} diff --git a/ilspy_dump/ror2_csproj/KeyValueUnsplitter.cs b/ilspy_dump/ror2_csproj/KeyValueUnsplitter.cs new file mode 100644 index 0000000..ea45caf --- /dev/null +++ b/ilspy_dump/ror2_csproj/KeyValueUnsplitter.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using HG; + +public struct KeyValueUnsplitter +{ + public readonly string baseKey; + + public KeyValueUnsplitter(string baseKey) + { + this.baseKey = baseKey; + } + + public string GetValue(IEnumerable> keyValues) + { + List> list = CollectionPool, List>>.RentCollection(); + foreach (KeyValuePair keyValue in keyValues) + { + if (keyValue.Key.EndsWith("]", StringComparison.Ordinal)) + { + int num = keyValue.Key.LastIndexOf("[", StringComparison.Ordinal); + string value = keyValue.Key.Substring(0, num); + if (baseKey.Equals(value, StringComparison.Ordinal) && int.TryParse(keyValue.Key.Substring(num + 1), out var result)) + { + list.Add(new KeyValuePair(result, keyValue.Value)); + } + } + else if (baseKey.Equals(keyValue.Key, StringComparison.Ordinal)) + { + return keyValue.Value; + } + } + list.Sort((KeyValuePair a, KeyValuePair b) => a.Key.CompareTo(b.Key)); + string result2 = string.Concat(list); + CollectionPool, List>>.ReturnCollection(list); + return result2; + } +} diff --git a/ilspy_dump/ror2_csproj/LightIntensityCurve.cs b/ilspy_dump/ror2_csproj/LightIntensityCurve.cs new file mode 100644 index 0000000..2a02b90 --- /dev/null +++ b/ilspy_dump/ror2_csproj/LightIntensityCurve.cs @@ -0,0 +1,80 @@ +using UnityEngine; + +public class LightIntensityCurve : MonoBehaviour +{ + public AnimationCurve curve; + + public float timeMax = 5f; + + private float time; + + private Light light; + + private float maxIntensity; + + [Tooltip("Loops the animation curve.")] + public bool loop; + + [Tooltip("Starts in a random point in the animation curve.")] + public bool randomStart; + + [Tooltip("Causes the lights to be negative, casting shadows instead.")] + public bool enableNegativeLights; + + private void Awake() + { + if ((bool)light || TryGetComponent(out light)) + { + maxIntensity = light.intensity; + } + } + + private void Start() + { + light.intensity = 0f; + if (randomStart) + { + time = Random.Range(0f, timeMax); + } + if (enableNegativeLights) + { + light.color = new Color(0f - light.color.r, 0f - light.color.g, 0f - light.color.b); + } + } + + private void OnEnable() + { + time = 0f; + if (!light) + { + light = GetComponent(); + } + light.intensity = 0f; + if (randomStart) + { + time = Random.Range(0f, timeMax); + } + if (enableNegativeLights) + { + light.color = new Color(0f - light.color.r, 0f - light.color.g, 0f - light.color.b); + } + } + + private void OnDisable() + { + if ((bool)light) + { + light.intensity = maxIntensity; + } + } + + private void Update() + { + time += Time.deltaTime; + light.intensity = curve.Evaluate(time / timeMax) * maxIntensity; + if (time >= timeMax && loop) + { + time = 0f; + } + } +} diff --git a/ilspy_dump/ror2_csproj/LineBetweenTransforms.cs b/ilspy_dump/ror2_csproj/LineBetweenTransforms.cs new file mode 100644 index 0000000..ec238b9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/LineBetweenTransforms.cs @@ -0,0 +1,65 @@ +using System; +using UnityEngine; +using UnityEngine.Serialization; + +[RequireComponent(typeof(LineRenderer))] +[ExecuteAlways] +public class LineBetweenTransforms : MonoBehaviour +{ + [SerializeField] + [FormerlySerializedAs("transformNodes")] + [Tooltip("The list of transforms whose positions will drive the vertex positions of the sibling LineRenderer component.")] + private Transform[] _transformNodes = Array.Empty(); + + private LineRenderer lineRenderer; + + private Vector3[] vertexList = Array.Empty(); + + public Transform[] transformNodes + { + get + { + return _transformNodes; + } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + _transformNodes = value; + UpdateVertexBufferSize(); + } + } + + private void PushPositionsToLineRenderer() + { + Vector3[] array = vertexList; + Transform[] array2 = transformNodes; + for (int i = 0; i < array.Length; i++) + { + Transform transform = array2[i]; + if ((bool)transform) + { + array[i] = transform.position; + } + } + lineRenderer.SetPositions(array); + } + + private void UpdateVertexBufferSize() + { + Array.Resize(ref vertexList, transformNodes.Length); + } + + private void Awake() + { + lineRenderer = GetComponent(); + UpdateVertexBufferSize(); + } + + private void LateUpdate() + { + PushPositionsToLineRenderer(); + } +} diff --git a/ilspy_dump/ror2_csproj/LoadHelper.cs b/ilspy_dump/ror2_csproj/LoadHelper.cs new file mode 100644 index 0000000..cc9e47c --- /dev/null +++ b/ilspy_dump/ror2_csproj/LoadHelper.cs @@ -0,0 +1,42 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine.AddressableAssets; +using UnityEngine.ResourceManagement.AsyncOperations; +using UnityEngine.ResourceManagement.ResourceProviders; +using UnityEngine.SceneManagement; + +public static class LoadHelper +{ + private static Dictionary> currentSceneLoads = new Dictionary>(); + + public static AsyncOperationHandle StartLoadSceneAdditiveAsync(string _sceneGuid) + { + AsyncOperationHandle asyncOperationHandle = Addressables.LoadSceneAsync(_sceneGuid, LoadSceneMode.Additive, activateOnLoad: false); + if (!currentSceneLoads.ContainsKey(_sceneGuid)) + { + currentSceneLoads[_sceneGuid] = asyncOperationHandle; + } + return asyncOperationHandle; + } + + public static IEnumerator LoadSceneAdditivelyAsync(string _sceneGuid) + { + AsyncOperationHandle handler; + if (!currentSceneLoads.ContainsKey(_sceneGuid)) + { + handler = Addressables.LoadSceneAsync(_sceneGuid, LoadSceneMode.Additive, activateOnLoad: false); + yield return handler; + } + else + { + handler = currentSceneLoads[_sceneGuid]; + currentSceneLoads.Remove(_sceneGuid); + yield return handler; + } + Scene oldScene = SceneManager.GetActiveScene(); + SceneInstance newScene = handler.Result; + yield return newScene.ActivateAsync(); + SceneManager.SetActiveScene(newScene.Scene); + SceneManager.UnloadSceneAsync(oldScene); + } +} diff --git a/ilspy_dump/ror2_csproj/LoadingScreenCanvas.cs b/ilspy_dump/ror2_csproj/LoadingScreenCanvas.cs new file mode 100644 index 0000000..f9cbda7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/LoadingScreenCanvas.cs @@ -0,0 +1,38 @@ +using System; +using RoR2; +using RoR2.UI; +using UnityEngine; +using UnityEngine.SceneManagement; + +public class LoadingScreenCanvas : MonoBehaviour +{ + public static LoadingScreenCanvas Instance; + + public SpriteAsNumberManager percentage; + + public GameObject background; + + public LoadingScreenCanvas() + { + Instance = this; + } + + public void Awake() + { + UnityEngine.Object.DontDestroyOnLoad(base.gameObject); + RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnLoadComplete)); + SceneManager.sceneLoaded += OnSceneChange; + } + + private void OnLoadComplete() + { + SceneManager.sceneLoaded -= OnSceneChange; + Instance = null; + UnityEngine.Object.Destroy(base.gameObject); + } + + private void OnSceneChange(Scene a, LoadSceneMode b) + { + Instance.background.SetActive(a.name == "loadingbasic"); + } +} diff --git a/ilspy_dump/ror2_csproj/LunarWispFXController.cs b/ilspy_dump/ror2_csproj/LunarWispFXController.cs new file mode 100644 index 0000000..22b65c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/LunarWispFXController.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using UnityEngine; + +public class LunarWispFXController : MonoBehaviour +{ + public List FXParticles = new List(); + + private void Start() + { + } + + private void FixedUpdate() + { + } + + public void TurnOffFX() + { + for (int i = 0; i < FXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = FXParticles[i].emission; + emission.enabled = false; + } + } + + public void TurnOnFX() + { + for (int i = 0; i < FXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = FXParticles[i].emission; + emission.enabled = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/MaintainRotation.cs b/ilspy_dump/ror2_csproj/MaintainRotation.cs new file mode 100644 index 0000000..26f18a2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/MaintainRotation.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +[ExecuteAlways] +public class MaintainRotation : MonoBehaviour +{ + public Vector3 eulerAngles; + + private void Start() + { + } + + private void LateUpdate() + { + base.transform.eulerAngles = eulerAngles; + } +} diff --git a/ilspy_dump/ror2_csproj/MaulingRock.cs b/ilspy_dump/ror2_csproj/MaulingRock.cs new file mode 100644 index 0000000..465be9f --- /dev/null +++ b/ilspy_dump/ror2_csproj/MaulingRock.cs @@ -0,0 +1,113 @@ +using System.Runtime.InteropServices; +using RoR2; +using UnityEngine; +using UnityEngine.Networking; + +public class MaulingRock : NetworkBehaviour +{ + private HealthComponent myHealthComponent; + + public GameObject deathEffect; + + public float blastRadius = 1f; + + public float damage = 10f; + + public float damageCoefficient = 1f; + + public float scaleVarianceLow = 0.8f; + + public float scaleVarianceHigh = 1.2f; + + public float verticalOffset; + + [SyncVar] + private float scale; + + public float Networkscale + { + get + { + return scale; + } + [param: In] + set + { + SetSyncVar(value, ref scale, 1u); + } + } + + public override void OnStartServer() + { + base.OnStartServer(); + Networkscale = Random.Range(scaleVarianceLow, scaleVarianceHigh); + } + + private void Start() + { + myHealthComponent = GetComponent(); + base.transform.localScale = new Vector3(scale, scale, scale); + } + + private void FixedUpdate() + { + if (NetworkServer.active && myHealthComponent != null && !myHealthComponent.alive) + { + if (deathEffect != null) + { + EffectManager.SpawnEffect(deathEffect, new EffectData + { + origin = base.transform.position, + scale = blastRadius + }, transmit: true); + } + Object.Destroy(base.gameObject); + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(scale); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(scale); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + scale = reader.ReadSingle(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + scale = reader.ReadSingle(); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/MaulingRockZoneManager.cs b/ilspy_dump/ror2_csproj/MaulingRockZoneManager.cs new file mode 100644 index 0000000..0f39b22 --- /dev/null +++ b/ilspy_dump/ror2_csproj/MaulingRockZoneManager.cs @@ -0,0 +1,118 @@ +using System.Collections; +using System.Collections.Generic; +using RoR2; +using RoR2.Projectile; +using UnityEngine; +using UnityEngine.Networking; + +public class MaulingRockZoneManager : MonoBehaviour +{ + public List maulingRockProjectilePrefabs = new List(); + + public Transform startZonePoint1; + + public Transform startZonePoint2; + + public Transform endZonePoint1; + + public Transform endZonePoint2; + + public static float baseDuration = 60f; + + public float knockbackForce = 10000f; + + private Vector3 vectorBetweenStartPoints = Vector3.zero; + + private Vector3 vectorBetweenEndPoints = Vector3.zero; + + private Vector3 MediumRockBump = Vector3.zero; + + private Vector3 LargeRockBump = Vector3.zero; + + private int salvoMaximumCount = 10; + + private float timeBetweenSalvoShotsLow = 0.1f; + + private float timeBetweenSalvoShotsHigh = 1f; + + private float timeBetweenSalvosLow = 3f; + + private float timeBetweenSalvosHigh = 5f; + + private int salvoRockCount; + + private int currentSalvoCount; + + private void Awake() + { + if (!NetworkServer.active) + { + base.enabled = false; + } + } + + private void Start() + { + vectorBetweenStartPoints = startZonePoint2.position - startZonePoint1.position; + vectorBetweenEndPoints = endZonePoint2.position - endZonePoint1.position; + FireSalvo(); + } + + private void FireSalvo() + { + salvoRockCount = Random.Range(0, salvoMaximumCount); + currentSalvoCount = 0; + FireRock(); + } + + private void FireRock() + { + GameObject gameObject = maulingRockProjectilePrefabs[Random.Range(0, maulingRockProjectilePrefabs.Count)]; + Vector3 vector = startZonePoint1.position + Random.Range(0f, 1f) * vectorBetweenStartPoints; + Vector3 vector2 = endZonePoint1.position + Random.Range(0f, 1f) * vectorBetweenEndPoints; + MaulingRock component = gameObject.GetComponent(); + float num = Random.Range(0f, 4f); + num += component.verticalOffset; + vector = new Vector3(vector.x, vector.y + num, vector.z); + num = Random.Range(0f, 4f); + num += component.verticalOffset; + vector2 = new Vector3(vector2.x, vector2.y + num, vector2.z); + Ray ray = new Ray(vector, vector2 - vector); + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = gameObject; + fireProjectileInfo.position = ray.origin; + fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(ray.direction); + fireProjectileInfo.owner = null; + fireProjectileInfo.damage = component.damage * component.damageCoefficient; + fireProjectileInfo.force = knockbackForce; + fireProjectileInfo.crit = false; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.target = null; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + currentSalvoCount++; + StartCoroutine(WaitToFireAnotherRock()); + } + + public IEnumerator WaitToFireAnotherSalvo() + { + float seconds = Random.Range(timeBetweenSalvosLow, timeBetweenSalvosHigh); + yield return new WaitForSeconds(seconds); + FireSalvo(); + } + + public IEnumerator WaitToFireAnotherRock() + { + float seconds = Random.Range(timeBetweenSalvoShotsLow, timeBetweenSalvoShotsHigh); + if (currentSalvoCount >= salvoRockCount) + { + yield return null; + StartCoroutine(WaitToFireAnotherSalvo()); + } + else + { + yield return new WaitForSeconds(seconds); + FireRock(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/MemoizedToString.cs b/ilspy_dump/ror2_csproj/MemoizedToString.cs new file mode 100644 index 0000000..c65191f --- /dev/null +++ b/ilspy_dump/ror2_csproj/MemoizedToString.cs @@ -0,0 +1,39 @@ +using System; + +public struct MemoizedToString where TInput : IEquatable where TToString : struct, IToStringImplementation +{ + private TInput lastInput; + + private string lastOutput; + + private TToString implementation; + + private static readonly MemoizedToString defaultValue; + + public string GetString(in TInput input) + { + if (!input.Equals(lastInput)) + { + lastInput = input; + lastOutput = implementation.DoToString(in lastInput); + } + return lastOutput; + } + + public static MemoizedToString GetNew() + { + return defaultValue; + } + + static MemoizedToString() + { + TInput input = default(TInput); + TToString val = default(TToString); + defaultValue = new MemoizedToString + { + lastInput = input, + lastOutput = val.DoToString(in input), + implementation = val + }; + } +} diff --git a/ilspy_dump/ror2_csproj/MoveCurve.cs b/ilspy_dump/ror2_csproj/MoveCurve.cs new file mode 100644 index 0000000..fa093f4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/MoveCurve.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +public class MoveCurve : MonoBehaviour +{ + public bool animateX; + + public bool animateY; + + public bool animateZ; + + public float curveScale = 1f; + + public AnimationCurve moveCurve; + + private float xValue; + + private float yValue; + + private float zValue; + + private void Start() + { + } + + private void Update() + { + if (animateX) + { + xValue = moveCurve.Evaluate(Time.time % (float)moveCurve.length) * curveScale; + } + else + { + xValue = base.transform.localPosition.x; + } + if (animateY) + { + yValue = moveCurve.Evaluate(Time.time % (float)moveCurve.length) * curveScale; + } + else + { + yValue = base.transform.localPosition.y; + } + if (animateZ) + { + zValue = moveCurve.Evaluate(Time.time % (float)moveCurve.length) * curveScale; + } + else + { + zValue = base.transform.localPosition.z; + } + base.transform.localPosition = new Vector3(xValue, yValue, zValue); + } +} diff --git a/ilspy_dump/ror2_csproj/NearestPlayerCheckerSingleton.cs b/ilspy_dump/ror2_csproj/NearestPlayerCheckerSingleton.cs new file mode 100644 index 0000000..d1d93aa --- /dev/null +++ b/ilspy_dump/ror2_csproj/NearestPlayerCheckerSingleton.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class NearestPlayerCheckerSingleton : MonoBehaviour +{ + public bool debugPrintInfo; + + public static NearestPlayerCheckerSingleton instance; +} diff --git a/ilspy_dump/ror2_csproj/NetworkLerpedAngle.cs b/ilspy_dump/ror2_csproj/NetworkLerpedAngle.cs new file mode 100644 index 0000000..8fc409e --- /dev/null +++ b/ilspy_dump/ror2_csproj/NetworkLerpedAngle.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +public struct NetworkLerpedAngle +{ + private const float interpDuration = 0.05f; + + private const float invInterpDuration = 20f; + + public float authoritativeValue; + + private float interpStartValue; + + private float interpStartTime; + + public float GetCurrentValue(bool hasAuthority) + { + if (hasAuthority) + { + return authoritativeValue; + } + float t = Mathf.Clamp01((Time.time - interpStartTime) * 20f); + return Mathf.LerpAngle(interpStartValue, authoritativeValue, t); + } + + public void SetAuthoritativeValue(float newValue, bool hasAuthority) + { + interpStartValue = GetCurrentValue(hasAuthority); + interpStartTime = Time.time; + authoritativeValue = newValue; + } +} diff --git a/ilspy_dump/ror2_csproj/NetworkLerpedAngleNew.cs b/ilspy_dump/ror2_csproj/NetworkLerpedAngleNew.cs new file mode 100644 index 0000000..884dd9f --- /dev/null +++ b/ilspy_dump/ror2_csproj/NetworkLerpedAngleNew.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +public struct NetworkLerpedAngleNew +{ + private struct InterpPoint + { + public float time; + + public float value; + } + + private const float interpDelay = 0.1f; + + private InterpPoint lowInterpPoint; + + private InterpPoint highInterpPoint; + + private InterpPoint newestInterpPoint; + + private float inverseLowHighTimespan; + + public void SetValueImmediate(float value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + highInterpPoint = newestInterpPoint; + lowInterpPoint = newestInterpPoint; + inverseLowHighTimespan = 0f; + } + + public float GetCurrentValue(bool hasAuthority) + { + if (hasAuthority) + { + return newestInterpPoint.value; + } + float num = Time.time - 0.1f; + if (num > highInterpPoint.time) + { + lowInterpPoint = highInterpPoint; + highInterpPoint = newestInterpPoint; + float num2 = highInterpPoint.time - lowInterpPoint.time; + inverseLowHighTimespan = ((num2 == 0f) ? 0f : (1f / num2)); + } + float t = Mathf.Clamp01((num - lowInterpPoint.time) * inverseLowHighTimespan); + return Mathf.LerpAngle(lowInterpPoint.value, highInterpPoint.value, t); + } + + public float GetAuthoritativeValue() + { + return newestInterpPoint.value; + } + + public void PushValue(float value) + { + if (newestInterpPoint.value != value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + } + } +} diff --git a/ilspy_dump/ror2_csproj/NetworkLerpedFloat.cs b/ilspy_dump/ror2_csproj/NetworkLerpedFloat.cs new file mode 100644 index 0000000..ac77631 --- /dev/null +++ b/ilspy_dump/ror2_csproj/NetworkLerpedFloat.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +public struct NetworkLerpedFloat +{ + private struct InterpPoint + { + public float time; + + public float value; + } + + private const float interpDelay = 0.1f; + + private InterpPoint lowInterpPoint; + + private InterpPoint highInterpPoint; + + private InterpPoint newestInterpPoint; + + private float inverseLowHighTimespan; + + public void SetValueImmediate(float value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + highInterpPoint = newestInterpPoint; + lowInterpPoint = newestInterpPoint; + inverseLowHighTimespan = 0f; + } + + public float GetCurrentValue(bool hasAuthority) + { + if (hasAuthority) + { + return newestInterpPoint.value; + } + float num = Time.time - 0.1f; + if (num > highInterpPoint.time) + { + lowInterpPoint = highInterpPoint; + highInterpPoint = newestInterpPoint; + float num2 = highInterpPoint.time - lowInterpPoint.time; + inverseLowHighTimespan = ((num2 == 0f) ? 0f : (1f / num2)); + } + float t = (num - lowInterpPoint.time) * inverseLowHighTimespan; + return Mathf.Lerp(lowInterpPoint.value, highInterpPoint.value, t); + } + + public float GetAuthoritativeValue() + { + return newestInterpPoint.value; + } + + public void PushValue(float value) + { + if (newestInterpPoint.value != value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + } + } +} diff --git a/ilspy_dump/ror2_csproj/NetworkLerpedQuaternion.cs b/ilspy_dump/ror2_csproj/NetworkLerpedQuaternion.cs new file mode 100644 index 0000000..3548d5b --- /dev/null +++ b/ilspy_dump/ror2_csproj/NetworkLerpedQuaternion.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +public struct NetworkLerpedQuaternion +{ + private struct InterpPoint + { + public float time; + + public Quaternion value; + } + + private const float interpDelay = 0.1f; + + private InterpPoint lowInterpPoint; + + private InterpPoint highInterpPoint; + + private InterpPoint newestInterpPoint; + + private float inverseLowHighTimespan; + + public void SetValueImmediate(Quaternion value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + highInterpPoint = newestInterpPoint; + lowInterpPoint = newestInterpPoint; + inverseLowHighTimespan = 0f; + } + + public Quaternion GetCurrentValue(bool hasAuthority) + { + if (hasAuthority) + { + return newestInterpPoint.value; + } + float num = Time.time - 0.1f; + if (num > highInterpPoint.time) + { + lowInterpPoint = highInterpPoint; + highInterpPoint = newestInterpPoint; + float num2 = highInterpPoint.time - lowInterpPoint.time; + inverseLowHighTimespan = ((num2 == 0f) ? 0f : (1f / num2)); + } + float t = (num - lowInterpPoint.time) * inverseLowHighTimespan; + return Quaternion.Slerp(lowInterpPoint.value, highInterpPoint.value, t); + } + + public Quaternion GetAuthoritativeValue() + { + return newestInterpPoint.value; + } + + public void PushValue(Quaternion value) + { + if (newestInterpPoint.value != value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + } + } +} diff --git a/ilspy_dump/ror2_csproj/NetworkLerpedVector3.cs b/ilspy_dump/ror2_csproj/NetworkLerpedVector3.cs new file mode 100644 index 0000000..8509ee6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/NetworkLerpedVector3.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +public struct NetworkLerpedVector3 +{ + private struct InterpPoint + { + public float time; + + public Vector3 value; + } + + public float interpDelay; + + private InterpPoint lowInterpPoint; + + private InterpPoint highInterpPoint; + + private InterpPoint newestInterpPoint; + + private float inverseLowHighTimespan; + + public void SetValueImmediate(Vector3 value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + highInterpPoint = newestInterpPoint; + lowInterpPoint = newestInterpPoint; + inverseLowHighTimespan = 0f; + } + + public Vector3 GetCurrentValue(bool hasAuthority) + { + if (hasAuthority) + { + return newestInterpPoint.value; + } + float num = Time.time - interpDelay; + if (num > highInterpPoint.time) + { + lowInterpPoint = highInterpPoint; + highInterpPoint = newestInterpPoint; + float num2 = highInterpPoint.time - lowInterpPoint.time; + inverseLowHighTimespan = ((num2 == 0f) ? 0f : (1f / num2)); + } + float t = (num - lowInterpPoint.time) * inverseLowHighTimespan; + return Vector3.Lerp(lowInterpPoint.value, highInterpPoint.value, t); + } + + public Vector3 GetAuthoritativeValue() + { + return newestInterpPoint.value; + } + + public void PushValue(Vector3 value) + { + if (newestInterpPoint.value != value) + { + newestInterpPoint.time = Time.time; + newestInterpPoint.value = value; + } + } +} diff --git a/ilspy_dump/ror2_csproj/NetworkManagerConfiguration.cs b/ilspy_dump/ror2_csproj/NetworkManagerConfiguration.cs new file mode 100644 index 0000000..809f6ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/NetworkManagerConfiguration.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Networking; + +public class NetworkManagerConfiguration : MonoBehaviour +{ + public new bool DontDestroyOnLoad = true; + + public bool RunInBackground = true; + + public LogFilter.FilterLevel LogLevel = LogFilter.FilterLevel.Info; + + public string OfflineScene; + + public string OnlineScene; + + public GameObject PlayerPrefab; + + public bool AutoCreatePlayer = true; + + public PlayerSpawnMethod PlayerSpawnMethod; + + public List SpawnPrefabs = new List(); + + public bool CustomConfig; + + public int MaxConnections = 4; + + public List QosChannels = new List(); +} diff --git a/ilspy_dump/ror2_csproj/OnEnableRestartChildParticleSystems.cs b/ilspy_dump/ror2_csproj/OnEnableRestartChildParticleSystems.cs new file mode 100644 index 0000000..9025a63 --- /dev/null +++ b/ilspy_dump/ror2_csproj/OnEnableRestartChildParticleSystems.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using UnityEngine; + +public class OnEnableRestartChildParticleSystems : MonoBehaviour +{ + [SerializeField] + private List particleSystemList = new List(); + + private void OnEnable() + { + if (particleSystemList == null || particleSystemList.Count <= 0) + { + return; + } + foreach (ParticleSystem particleSystem in particleSystemList) + { + if (!particleSystem.isPlaying) + { + particleSystem.Play(); + } + } + } + + private void OnDisable() + { + if (particleSystemList == null || particleSystemList.Count <= 0) + { + return; + } + foreach (ParticleSystem particleSystem in particleSystemList) + { + particleSystem.Stop(); + particleSystem.Clear(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/OnParticleEndEvent.cs b/ilspy_dump/ror2_csproj/OnParticleEndEvent.cs new file mode 100644 index 0000000..873f186 --- /dev/null +++ b/ilspy_dump/ror2_csproj/OnParticleEndEvent.cs @@ -0,0 +1,20 @@ +using UnityEngine; +using UnityEngine.Events; + +public class OnParticleEndEvent : MonoBehaviour +{ + public ParticleSystem particleSystemToTrack; + + public UnityEvent onEnd; + + private bool particleEnded; + + public void Update() + { + if ((bool)particleSystemToTrack && !particleSystemToTrack.IsAlive() && !particleEnded) + { + particleEnded = true; + onEnd.Invoke(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/Optimization/WanderCulling.cs b/ilspy_dump/ror2_csproj/Optimization/WanderCulling.cs new file mode 100644 index 0000000..ffa6905 --- /dev/null +++ b/ilspy_dump/ror2_csproj/Optimization/WanderCulling.cs @@ -0,0 +1,16 @@ +namespace Optimization; + +public static class WanderCulling +{ + public const float wanderTimeBeforeCull = 15f; + + public const float wanderResetTime = 7.5f; + + public const float minLifeTime = 20f; + + public const float wanderPlayerCheckRadius = 75f; + + public const int minEnemyCountBeforeCull = 10; + + public const int importanceThreshold = 3; +} diff --git a/ilspy_dump/ror2_csproj/OrbEffectSingleton.cs b/ilspy_dump/ror2_csproj/OrbEffectSingleton.cs new file mode 100644 index 0000000..86a13de --- /dev/null +++ b/ilspy_dump/ror2_csproj/OrbEffectSingleton.cs @@ -0,0 +1,55 @@ +using RoR2.Orbs; +using UnityEngine; + +public class OrbEffectSingleton : MonoBehaviour +{ + public static OrbEffectSingleton instance; + + public static OrbEffect[] orbEffectArray; + + public static int numPnts; + + private void Awake() + { + if (instance != null) + { + Object.DestroyImmediate(this); + return; + } + instance = this; + orbEffectArray = new OrbEffect[50]; + } + + public static void RegisterInstance(OrbEffect newOrbEffect) + { + if (orbEffectArray == null || orbEffectArray.Length == numPnts) + { + OrbEffect[] array = new OrbEffect[(int)((float)(numPnts + 1) * 1.5f)]; + orbEffectArray.CopyTo(array, 0); + orbEffectArray = array; + } + newOrbEffect.singletonArrayIndex = numPnts; + orbEffectArray[numPnts] = newOrbEffect; + numPnts++; + } + + public static void UnregisterInstance(OrbEffect orbToDisable) + { + int singletonArrayIndex = orbToDisable.singletonArrayIndex; + if (singletonArrayIndex != numPnts - 1) + { + orbEffectArray[singletonArrayIndex] = orbEffectArray[numPnts - 1]; + orbEffectArray[singletonArrayIndex].singletonArrayIndex = singletonArrayIndex; + } + orbToDisable.singletonArrayIndex = -1; + numPnts--; + } + + public void Update() + { + for (int i = 0; i < numPnts; i++) + { + orbEffectArray[i].UpdateOrb(Time.deltaTime); + } + } +} diff --git a/ilspy_dump/ror2_csproj/POISecretChest.cs b/ilspy_dump/ror2_csproj/POISecretChest.cs new file mode 100644 index 0000000..e67c3c4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/POISecretChest.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class POISecretChest : MonoBehaviour +{ + public float influence = 5f; + + private void OnDrawGizmos() + { + Gizmos.matrix = base.transform.localToWorldMatrix; + Gizmos.color = new Color(0f, 1f, 1f, 0.03f); + Gizmos.DrawCube(Vector3.zero, base.transform.localScale / 2f); + Gizmos.color = new Color(0f, 1f, 1f, 0.1f); + Gizmos.DrawWireCube(Vector3.zero, base.transform.localScale / 2f); + } +} diff --git a/ilspy_dump/ror2_csproj/PS4Timer.cs b/ilspy_dump/ror2_csproj/PS4Timer.cs new file mode 100644 index 0000000..4207493 --- /dev/null +++ b/ilspy_dump/ror2_csproj/PS4Timer.cs @@ -0,0 +1,3 @@ +public class PS4Timer +{ +} diff --git a/ilspy_dump/ror2_csproj/ParentEnergyFXController.cs b/ilspy_dump/ror2_csproj/ParentEnergyFXController.cs new file mode 100644 index 0000000..22ec951 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ParentEnergyFXController.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using UnityEngine; + +public class ParentEnergyFXController : MonoBehaviour +{ + public List energyFXParticles = new List(); + + public ParticleSystem loomingPresenceParticles; + + private void Start() + { + } + + private void FixedUpdate() + { + } + + public void TurnOffFX() + { + for (int i = 0; i < energyFXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = energyFXParticles[i].emission; + emission.enabled = false; + } + } + + public void TurnOnFX() + { + for (int i = 0; i < energyFXParticles.Count; i++) + { + ParticleSystem.EmissionModule emission = energyFXParticles[i].emission; + emission.enabled = true; + } + } + + public void SetLoomingPresenceParticles(bool setTo) + { + ParticleSystem.EmissionModule emission = loomingPresenceParticles.emission; + emission.enabled = setTo; + } +} diff --git a/ilspy_dump/ror2_csproj/Particle_SetMinSize.cs b/ilspy_dump/ror2_csproj/Particle_SetMinSize.cs new file mode 100644 index 0000000..2f772b6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/Particle_SetMinSize.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class Particle_SetMinSize : MonoBehaviour +{ + public float minimumPixelCoverage = 2f; + + public float defaultMinimumParticleSize; + + [SerializeField] + private bool _isEnabled = true; + + private void Start() + { + UpdateMinSize(); + } + + public void SetEnabled(bool isEnabled) + { + _isEnabled = isEnabled; + UpdateMinSize(); + } + + private void UpdateMinSize() + { + GetComponent().minParticleSize = (_isEnabled ? (minimumPixelCoverage / (float)Screen.width) : defaultMinimumParticleSize); + } +} diff --git a/ilspy_dump/ror2_csproj/PauseTintController.cs b/ilspy_dump/ror2_csproj/PauseTintController.cs new file mode 100644 index 0000000..be422dd --- /dev/null +++ b/ilspy_dump/ror2_csproj/PauseTintController.cs @@ -0,0 +1,37 @@ +using System; +using RoR2; +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class PauseTintController : MonoBehaviour +{ + private PostProcessVolume ppPauseVolume; + + private void Awake() + { + ppPauseVolume = GetComponent(); + ppPauseVolume.enabled = false; + } + + private void OnEnable() + { + PauseManager.onPauseStartGlobal = (Action)Delegate.Combine(PauseManager.onPauseStartGlobal, new Action(OnPauseStart)); + PauseManager.onPauseEndGlobal = (Action)Delegate.Combine(PauseManager.onPauseEndGlobal, new Action(OnPauseEnd)); + } + + private void OnDisable() + { + PauseManager.onPauseStartGlobal = (Action)Delegate.Remove(PauseManager.onPauseStartGlobal, new Action(OnPauseStart)); + PauseManager.onPauseEndGlobal = (Action)Delegate.Remove(PauseManager.onPauseEndGlobal, new Action(OnPauseEnd)); + } + + private void OnPauseStart() + { + ppPauseVolume.enabled = true; + } + + private void OnPauseEnd() + { + ppPauseVolume.enabled = false; + } +} diff --git a/ilspy_dump/ror2_csproj/PhysicsController.cs b/ilspy_dump/ror2_csproj/PhysicsController.cs new file mode 100644 index 0000000..a39c89b --- /dev/null +++ b/ilspy_dump/ror2_csproj/PhysicsController.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +public class PhysicsController : MonoBehaviour +{ + public Vector3 centerOfMass = Vector3.zero; + + private Rigidbody carRigidbody; + + public Transform cameraTransform; + + public Vector3 PID = new Vector3(1f, 0f, 0f); + + public bool turnOnInput; + + private Vector3 errorSum = Vector3.zero; + + private Vector3 deltaError = Vector3.zero; + + private Vector3 lastError = Vector3.zero; + + private Vector3 desiredHeading; + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.red; + Gizmos.DrawSphere(base.transform.TransformPoint(centerOfMass), 0.5f); + } + + private void Awake() + { + carRigidbody = GetComponent(); + } + + private void Update() + { + } + + private void FixedUpdate() + { + if (!turnOnInput || Input.GetAxis("Vertical") > 0f || Input.GetAxis("Vertical") > 0f) + { + desiredHeading = cameraTransform.forward; + desiredHeading = Vector3.Project(desiredHeading, base.transform.forward); + desiredHeading = cameraTransform.forward - desiredHeading; + Debug.DrawRay(base.transform.position, desiredHeading * 15f, Color.magenta); + } + Vector3 vector = -base.transform.up; + Debug.DrawRay(base.transform.position, vector * 15f, Color.blue); + Vector3 vector2 = Vector3.Cross(vector, desiredHeading); + Debug.DrawRay(base.transform.position, vector2 * 15f, Color.red); + vector2.x = 0f; + vector2.z = 0f; + errorSum += vector2 * Time.fixedDeltaTime; + deltaError = (vector2 - lastError) / Time.fixedDeltaTime; + lastError = vector2; + carRigidbody.AddTorque(vector2 * PID.x + errorSum * PID.y + deltaError * PID.z, ForceMode.Acceleration); + } +} diff --git a/ilspy_dump/ror2_csproj/PhysicsImpactSpeedModifier.cs b/ilspy_dump/ror2_csproj/PhysicsImpactSpeedModifier.cs new file mode 100644 index 0000000..262ac58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/PhysicsImpactSpeedModifier.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +[RequireComponent(typeof(Rigidbody))] +public class PhysicsImpactSpeedModifier : MonoBehaviour +{ + public float normalSpeedModifier; + + public float perpendicularSpeedModifier; + + private Rigidbody rigid; + + private void Awake() + { + rigid = GetComponent(); + } + + private void OnCollisionEnter(Collision collision) + { + Vector3 normal = collision.contacts[0].normal; + Vector3 velocity = rigid.velocity; + Vector3 vector = Vector3.Project(velocity, normal); + Vector3 vector2 = velocity - vector; + vector *= normalSpeedModifier; + vector2 *= perpendicularSpeedModifier; + rigid.velocity = vector + vector2; + } +} diff --git a/ilspy_dump/ror2_csproj/PiaMatchmaker.cs b/ilspy_dump/ror2_csproj/PiaMatchmaker.cs new file mode 100644 index 0000000..bd3b8a1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/PiaMatchmaker.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class PiaMatchmaker : MonoBehaviour +{ +} diff --git a/ilspy_dump/ror2_csproj/PiaNetworkTransport.cs b/ilspy_dump/ror2_csproj/PiaNetworkTransport.cs new file mode 100644 index 0000000..1f2fb6f --- /dev/null +++ b/ilspy_dump/ror2_csproj/PiaNetworkTransport.cs @@ -0,0 +1,140 @@ +using System.Net; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.Networking.Types; + +public class PiaNetworkTransport : INetworkTransport +{ + public bool IsStarted => NetworkTransport.IsStarted; + + public int AddHost(HostTopology topology, int port, string ip) + { + Debug.LogFormat($"PiaNetworkTransport::AddHost: topology: {0}, port: {1}, ip: {2}", topology.ToString(), port, ip); + return NetworkTransport.AddHost(topology, 7777, "localhost"); + } + + public int AddHostWithSimulator(HostTopology topology, int minTimeout, int maxTimeout, int port) + { + return NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout, port); + } + + public int AddWebsocketHost(HostTopology topology, int port, string ip) + { + return NetworkTransport.AddWebsocketHost(topology, port, ip); + } + + public int Connect(int hostId, string address, int port, int specialConnectionId, out byte error) + { + return NetworkTransport.Connect(hostId, address, port, specialConnectionId, out error); + } + + public void ConnectAsNetworkHost(int hostId, string address, int port, NetworkID network, SourceID source, NodeID node, out byte error) + { + NetworkTransport.ConnectAsNetworkHost(hostId, address, port, network, source, node, out error); + } + + public int ConnectEndPoint(int hostId, EndPoint endPoint, int specialConnectionId, out byte error) + { + return NetworkTransport.ConnectEndPoint(hostId, endPoint, specialConnectionId, out error); + } + + public int ConnectToNetworkPeer(int hostId, string address, int port, int specialConnectionId, int relaySlotId, NetworkID network, SourceID source, NodeID node, out byte error) + { + return NetworkTransport.ConnectToNetworkPeer(hostId, address, port, specialConnectionId, relaySlotId, network, source, node, out error); + } + + public int ConnectWithSimulator(int hostId, string address, int port, int specialConnectionId, out byte error, ConnectionSimulatorConfig conf) + { + return NetworkTransport.ConnectWithSimulator(hostId, address, port, specialConnectionId, out error, conf); + } + + public bool Disconnect(int hostId, int connectionId, out byte error) + { + return NetworkTransport.Disconnect(hostId, connectionId, out error); + } + + public bool DoesEndPointUsePlatformProtocols(EndPoint endPoint) + { + return true; + } + + public void GetBroadcastConnectionInfo(int hostId, out string address, out int port, out byte error) + { + NetworkTransport.GetBroadcastConnectionInfo(hostId, out address, out port, out error); + } + + public void GetBroadcastConnectionMessage(int hostId, byte[] buffer, int bufferSize, out int receivedSize, out byte error) + { + NetworkTransport.GetBroadcastConnectionMessage(hostId, buffer, bufferSize, out receivedSize, out error); + } + + public void GetConnectionInfo(int hostId, int connectionId, out string address, out int port, out NetworkID network, out NodeID dstNode, out byte error) + { + NetworkTransport.GetConnectionInfo(hostId, connectionId, out address, out port, out network, out dstNode, out error); + } + + public int GetCurrentRTT(int hostId, int connectionId, out byte error) + { + return NetworkTransport.GetCurrentRTT(hostId, connectionId, out error); + } + + public void Init() + { + NetworkTransport.Init(); + } + + public void Init(GlobalConfig config) + { + NetworkTransport.Init(config); + } + + public NetworkEventType Receive(out int hostId, out int connectionId, out int channelId, byte[] buffer, int bufferSize, out int receivedSize, out byte error) + { + return NetworkTransport.Receive(out hostId, out connectionId, out channelId, buffer, bufferSize, out receivedSize, out error); + } + + public NetworkEventType ReceiveFromHost(int hostId, out int connectionId, out int channelId, byte[] buffer, int bufferSize, out int receivedSize, out byte error) + { + return NetworkTransport.ReceiveFromHost(hostId, out connectionId, out channelId, buffer, bufferSize, out receivedSize, out error); + } + + public NetworkEventType ReceiveRelayEventFromHost(int hostId, out byte error) + { + return NetworkTransport.ReceiveRelayEventFromHost(hostId, out error); + } + + public bool RemoveHost(int hostId) + { + return NetworkTransport.RemoveHost(hostId); + } + + public bool Send(int hostId, int connectionId, int channelId, byte[] buffer, int size, out byte error) + { + return NetworkTransport.Send(hostId, connectionId, channelId, buffer, size, out error); + } + + public void SetBroadcastCredentials(int hostId, int key, int version, int subversion, out byte error) + { + NetworkTransport.SetBroadcastCredentials(hostId, key, version, subversion, out error); + } + + public void SetPacketStat(int direction, int packetStatId, int numMsgs, int numBytes) + { + NetworkTransport.SetPacketStat(direction, packetStatId, numMsgs, numBytes); + } + + public void Shutdown() + { + NetworkTransport.Shutdown(); + } + + public bool StartBroadcastDiscovery(int hostId, int broadcastPort, int key, int version, int subversion, byte[] buffer, int size, int timeout, out byte error) + { + return NetworkTransport.StartBroadcastDiscovery(hostId, broadcastPort, key, version, subversion, buffer, size, timeout, out error); + } + + public void StopBroadcastDiscovery() + { + NetworkTransport.StopBroadcastDiscovery(); + } +} diff --git a/ilspy_dump/ror2_csproj/PinnedKey.cs b/ilspy_dump/ror2_csproj/PinnedKey.cs new file mode 100644 index 0000000..e8762a8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/PinnedKey.cs @@ -0,0 +1,3 @@ +public class PinnedKey +{ +} diff --git a/ilspy_dump/ror2_csproj/PlatformVoiceChatManager.cs b/ilspy_dump/ror2_csproj/PlatformVoiceChatManager.cs new file mode 100644 index 0000000..64c16c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/PlatformVoiceChatManager.cs @@ -0,0 +1,9 @@ +using RoR2; + +public class PlatformVoiceChatManager +{ + public static VoiceChatManager Get() + { + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/PositionFromParentRaycast.cs b/ilspy_dump/ror2_csproj/PositionFromParentRaycast.cs new file mode 100644 index 0000000..f6a6f68 --- /dev/null +++ b/ilspy_dump/ror2_csproj/PositionFromParentRaycast.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class PositionFromParentRaycast : MonoBehaviour +{ + public float maxLength; + + public LayerMask mask; + + private void Update() + { + RaycastHit hitInfo = default(RaycastHit); + if (Physics.Raycast(base.transform.parent.position, base.transform.parent.forward, out hitInfo, maxLength, mask)) + { + base.transform.position = hitInfo.point; + } + else + { + base.transform.position = base.transform.parent.position + base.transform.parent.forward * maxLength; + } + } +} diff --git a/ilspy_dump/ror2_csproj/PrimeDevastatorProjectileController.cs b/ilspy_dump/ror2_csproj/PrimeDevastatorProjectileController.cs new file mode 100644 index 0000000..c9cce3d --- /dev/null +++ b/ilspy_dump/ror2_csproj/PrimeDevastatorProjectileController.cs @@ -0,0 +1,21 @@ +using RoR2.Projectile; +using UnityEngine; + +public class PrimeDevastatorProjectileController : MonoBehaviour +{ + public ProjectileOwnerOrbiter orbiter; + + public float expansionSpeed = 1f; + + private float orbitExpansionTimer; + + private void Start() + { + } + + private void Update() + { + ProjectileOwnerOrbiter projectileOwnerOrbiter = orbiter; + projectileOwnerOrbiter.Networkradius = projectileOwnerOrbiter.radius + Time.deltaTime * expansionSpeed; + } +} diff --git a/ilspy_dump/ror2_csproj/ProcessorAffinity.cs b/ilspy_dump/ror2_csproj/ProcessorAffinity.cs new file mode 100644 index 0000000..c1d58e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ProcessorAffinity.cs @@ -0,0 +1,3 @@ +public static class ProcessorAffinity +{ +} diff --git a/ilspy_dump/ror2_csproj/ProjectileGhostTriggerOnStick.cs b/ilspy_dump/ror2_csproj/ProjectileGhostTriggerOnStick.cs new file mode 100644 index 0000000..90e4e6f --- /dev/null +++ b/ilspy_dump/ror2_csproj/ProjectileGhostTriggerOnStick.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using UnityEngine.Events; + +public class ProjectileGhostTriggerOnStick : MonoBehaviour +{ + private Vector3 lastPosition; + + private Quaternion lastRotation; + + private bool begunMoving; + + private bool finishedMoving; + + [SerializeField] + [Tooltip("If the object is rotating, will we consider that movement?")] + private bool trackRotationAsMovement; + + [SerializeField] + private UnityEvent OnStick; + + private void OnEnable() + { + begunMoving = false; + finishedMoving = false; + lastPosition = base.transform.position; + lastRotation = base.transform.rotation; + } + + private void Update() + { + Vector3 position = base.transform.position; + Quaternion rotation = base.transform.rotation; + if (!begunMoving && position != lastPosition && (!trackRotationAsMovement || (trackRotationAsMovement && rotation != lastRotation))) + { + begunMoving = true; + } + else if (begunMoving && !finishedMoving && position == lastPosition && (!trackRotationAsMovement || (trackRotationAsMovement && rotation == lastRotation))) + { + RunStuckMethod(); + finishedMoving = true; + } + lastPosition = position; + lastRotation = rotation; + } + + public void RunStuckMethod() + { + OnStick.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/Properties/AssemblyInfo.cs b/ilspy_dump/ror2_csproj/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..576b291 --- /dev/null +++ b/ilspy_dump/ror2_csproj/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Security; +using System.Security.Permissions; +using HG.Reflection; + +[assembly: SearchableAttribute.OptIn] +[assembly: AssemblyVersion("0.0.0.0")] diff --git a/ilspy_dump/ror2_csproj/ProximityHighlight.cs b/ilspy_dump/ror2_csproj/ProximityHighlight.cs new file mode 100644 index 0000000..9691e24 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ProximityHighlight.cs @@ -0,0 +1,95 @@ +using System; +using RoR2; +using UnityEngine; + +public class ProximityHighlight : MonoBehaviour +{ + public float highlightRadius = 50f; + + public float highlightScale = 0.6f; + + public float highlightUpdateInterval = 0.1f; + + private float _highlightUpdateTimer; + + private CharacterMaster _characterMaster; + + private CharacterBody _characterBody; + + private InteractionDriver _interactionDriver; + + private Collider[] _hitColliders = new Collider[64]; + + private int _hits; + + private void Awake() + { + _characterMaster = GetComponent(); + base.enabled = TutorialManager.isTutorialEnabled; + } + + private void OnEnable() + { + OutlineHighlight.onPreRenderOutlineHighlight = (Action)Delegate.Combine(OutlineHighlight.onPreRenderOutlineHighlight, new Action(OnPreRenderOutlineHighlight)); + } + + private void OnDisable() + { + OutlineHighlight.onPreRenderOutlineHighlight = (Action)Delegate.Remove(OutlineHighlight.onPreRenderOutlineHighlight, new Action(OnPreRenderOutlineHighlight)); + } + + private void FixedUpdate() + { + if (!_characterMaster) + { + return; + } + _highlightUpdateTimer -= Time.fixedDeltaTime; + if (!(_highlightUpdateTimer < 0f)) + { + return; + } + _highlightUpdateTimer = highlightUpdateInterval; + _characterBody = _characterMaster.GetBody(); + if ((bool)_characterBody) + { + _interactionDriver = _characterBody.GetComponent(); + if ((bool)_interactionDriver) + { + Array.Clear(_hitColliders, 0, _hitColliders.Length); + _hits = Physics.OverlapSphereNonAlloc(_characterBody.transform.position, highlightRadius, _hitColliders, LayerIndex.CommonMasks.interactable, QueryTriggerInteraction.Collide); + } + } + } + + private void OnPreRenderOutlineHighlight(OutlineHighlight outlineHighlight) + { + for (int i = 0; i < _hits; i++) + { + if (!_hitColliders[i] || !_hitColliders[i].gameObject || !EntityLocator.HasEntityLocator(_hitColliders[i].gameObject, out var foundLocator)) + { + continue; + } + GameObject entity = foundLocator.entity; + if (_interactionDriver.currentInteractable == entity) + { + continue; + } + IInteractable component = entity.GetComponent(); + if (component != null && ((MonoBehaviour)component).isActiveAndEnabled && (bool)_interactionDriver.interactor && component.GetInteractability(_interactionDriver.interactor) != 0 && component.ShouldProximityHighlight()) + { + Highlight component2 = entity.GetComponent(); + if (!component2) + { + break; + } + Color color = component2.GetColor() * component2.strength * highlightScale; + outlineHighlight.highlightQueue.Enqueue(new OutlineHighlight.HighlightInfo + { + renderer = component2.targetRenderer, + color = color + }); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/QuaternionPID.cs b/ilspy_dump/ror2_csproj/QuaternionPID.cs new file mode 100644 index 0000000..18d6a31 --- /dev/null +++ b/ilspy_dump/ror2_csproj/QuaternionPID.cs @@ -0,0 +1,66 @@ +using UnityEngine; +using UnityEngine.Serialization; + +public class QuaternionPID : MonoBehaviour +{ + [Tooltip("Just a field for user naming. Doesn't do anything.")] + [FormerlySerializedAs("name")] + public string customName; + + [Tooltip("PID Constants.")] + public Vector3 PID = new Vector3(1f, 0f, 0f); + + [Tooltip("The quaternion we are currently at.")] + public Quaternion inputQuat = Quaternion.identity; + + [Tooltip("The quaternion we want to be at.")] + public Quaternion targetQuat = Quaternion.identity; + + [Tooltip("Vector output from PID controller; what we read.")] + [HideInInspector] + public Vector3 outputVector = Vector3.zero; + + public float gain = 1f; + + private Vector3 errorSum = Vector3.zero; + + private Vector3 deltaError = Vector3.zero; + + private Vector3 lastError = Vector3.zero; + + private float lastUpdateTime; + + private void Start() + { + gain *= 60f * Time.fixedDeltaTime; + lastUpdateTime = Time.time; + } + + public Vector3 UpdatePID() + { + float time = Time.time; + float num = time - lastUpdateTime; + lastUpdateTime = time; + if (num != 0f) + { + Quaternion quaternion = targetQuat * Quaternion.Inverse(inputQuat); + if (quaternion.w < 0f) + { + quaternion.x *= -1f; + quaternion.y *= -1f; + quaternion.z *= -1f; + quaternion.w *= -1f; + } + Vector3 vector = default(Vector3); + vector.x = quaternion.x; + vector.y = quaternion.y; + vector.z = quaternion.z; + errorSum += vector * num; + deltaError = (vector - lastError) / num; + lastError = vector; + outputVector = vector * PID.x + errorSum * PID.y + deltaError * PID.z; + return outputVector * gain; + } + return Vector3.zero; + } +} diff --git a/ilspy_dump/ror2_csproj/QuickStopwatch.cs b/ilspy_dump/ror2_csproj/QuickStopwatch.cs new file mode 100644 index 0000000..fe01236 --- /dev/null +++ b/ilspy_dump/ror2_csproj/QuickStopwatch.cs @@ -0,0 +1,28 @@ +using System.Diagnostics; +using System.Runtime.CompilerServices; + +public static class QuickStopwatch +{ + private static string m_name; + + private static Stopwatch m_stopwatch = new Stopwatch(); + + private static long m_lapTime = 0L; + + private static int m_lap = 0; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Begin(string name) + { + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void End() + { + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Lap(string addText = "") + { + } +} diff --git a/ilspy_dump/ror2_csproj/RJShroomBounce.cs b/ilspy_dump/ror2_csproj/RJShroomBounce.cs new file mode 100644 index 0000000..8368e5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RJShroomBounce.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class RJShroomBounce : MonoBehaviour +{ + private Animator shroomAnimator; + + public void Start() + { + shroomAnimator = GetComponent(); + } + + public void Bounce() + { + shroomAnimator.Play("Bounce", 0); + } +} diff --git a/ilspy_dump/ror2_csproj/RampFog.cs b/ilspy_dump/ror2_csproj/RampFog.cs new file mode 100644 index 0000000..a497c5b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RampFog.cs @@ -0,0 +1,82 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +[Serializable] +[PostProcess(typeof(RampFogRenderer), PostProcessEvent.BeforeTransparent, "PostProcess/RampFog", true)] +public sealed class RampFog : PostProcessEffectSettings +{ + [Range(0f, 1f)] + [Tooltip("Fog intensity.")] + public FloatParameter fogIntensity = new FloatParameter + { + value = 0.5f + }; + + [Range(0f, 20f)] + [Tooltip("Fog Power")] + public FloatParameter fogPower = new FloatParameter + { + value = 1f + }; + + [Range(-1f, 1f)] + [Tooltip("The zero value for the fog depth remap.")] + public FloatParameter fogZero = new FloatParameter + { + value = 0f + }; + + [Tooltip("The one value for the fog depth remap.")] + [Range(-1f, 1f)] + public FloatParameter fogOne = new FloatParameter + { + value = 1f + }; + + [Range(-100f, 100f)] + [Tooltip("The world position value where the height fog begins.")] + public FloatParameter fogHeightStart = new FloatParameter + { + value = 0f + }; + + [Range(-100f, 600f)] + [Tooltip("The world position value where the height fog ends.")] + public FloatParameter fogHeightEnd = new FloatParameter + { + value = 100f + }; + + [Range(0f, 5f)] + [Tooltip("The overall strength of the height fog.")] + public FloatParameter fogHeightIntensity = new FloatParameter + { + value = 0f + }; + + [Tooltip("Color of the fog at the beginning.")] + public ColorParameter fogColorStart = new ColorParameter + { + value = Color.white + }; + + [Tooltip("Color of the fog at the middle.")] + public ColorParameter fogColorMid = new ColorParameter + { + value = Color.white + }; + + [Tooltip("Color of the fog at the end.")] + public ColorParameter fogColorEnd = new ColorParameter + { + value = Color.white + }; + + [Tooltip("How much of the skybox will leak through?")] + [Range(0f, 1f)] + public FloatParameter skyboxStrength = new FloatParameter + { + value = 0f + }; +} diff --git a/ilspy_dump/ror2_csproj/RampFogRenderer.cs b/ilspy_dump/ror2_csproj/RampFogRenderer.cs new file mode 100644 index 0000000..706fcc6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RampFogRenderer.cs @@ -0,0 +1,22 @@ +using RoR2; +using UnityEngine.Rendering.PostProcessing; + +public sealed class RampFogRenderer : PostProcessEffectRenderer +{ + public override void Render(PostProcessRenderContext context) + { + PropertySheet propertySheet = context.propertySheets.Get(LegacyShaderAPI.Find("Hidden/PostProcess/RampFog")); + propertySheet.properties.SetFloat("_FogIntensity", base.settings.fogIntensity); + propertySheet.properties.SetFloat("_FogPower", base.settings.fogPower); + propertySheet.properties.SetFloat("_FogZero", base.settings.fogZero); + propertySheet.properties.SetFloat("_FogOne", base.settings.fogOne); + propertySheet.properties.SetFloat("_FogHeightStart", base.settings.fogHeightStart); + propertySheet.properties.SetFloat("_FogHeightEnd", base.settings.fogHeightEnd); + propertySheet.properties.SetFloat("_FogHeightIntensity", base.settings.fogHeightIntensity); + propertySheet.properties.SetColor("_FogColorStart", base.settings.fogColorStart); + propertySheet.properties.SetColor("_FogColorMid", base.settings.fogColorMid); + propertySheet.properties.SetColor("_FogColorEnd", base.settings.fogColorEnd); + propertySheet.properties.SetFloat("_SkyboxStrength", base.settings.skyboxStrength); + context.command.BlitFullscreenTriangle(context.source, context.destination, propertySheet, 0); + } +} diff --git a/ilspy_dump/ror2_csproj/ReadOnlyAttribute.cs b/ilspy_dump/ror2_csproj/ReadOnlyAttribute.cs new file mode 100644 index 0000000..8d0d087 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ReadOnlyAttribute.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class ReadOnlyAttribute : PropertyAttribute +{ +} diff --git a/ilspy_dump/ror2_csproj/RenderDepth.cs b/ilspy_dump/ror2_csproj/RenderDepth.cs new file mode 100644 index 0000000..d9c35d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RenderDepth.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +[ExecuteInEditMode] +public class RenderDepth : MonoBehaviour +{ + private void OnEnable() + { + GetComponent().depthTextureMode = DepthTextureMode.DepthNormals; + } +} diff --git a/ilspy_dump/ror2_csproj/RenderInFrontOfParticles.cs b/ilspy_dump/ror2_csproj/RenderInFrontOfParticles.cs new file mode 100644 index 0000000..3a4a199 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RenderInFrontOfParticles.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class RenderInFrontOfParticles : MonoBehaviour +{ + public int renderOrder; + + private Renderer rend; + + private void Start() + { + rend = GetComponent(); + rend.material.renderQueue = renderOrder; + } + + private void Update() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RenderSettingsState.cs b/ilspy_dump/ror2_csproj/RenderSettingsState.cs new file mode 100644 index 0000000..1cf1f54 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RenderSettingsState.cs @@ -0,0 +1,118 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering; + +[Serializable] +public struct RenderSettingsState +{ + public float haloStrength; + + public int defaultReflectionResolution; + + public DefaultReflectionMode defaultReflectionMode; + + public int reflectionBounces; + + public float reflectionIntensity; + + public Texture customReflection; + + public SphericalHarmonicsL2 ambientProbe; + + public Light sun; + + public Material skybox; + + public Color subtractiveShadowColor; + + public float flareStrength; + + [ColorUsage(false, true)] + public Color ambientLight; + + [ColorUsage(false, true)] + public Color ambientGroundColor; + + [ColorUsage(false, true)] + public Color ambientEquatorColor; + + [ColorUsage(false, true)] + public Color ambientSkyColor; + + public AmbientMode ambientMode; + + public float fogDensity; + + [ColorUsage(true, false)] + public Color fogColor; + + public FogMode fogMode; + + public float fogEndDistance; + + public float fogStartDistance; + + public bool fog; + + public float ambientIntensity; + + public float flareFadeSpeed; + + public static RenderSettingsState FromCurrent() + { + RenderSettingsState result = default(RenderSettingsState); + result.haloStrength = RenderSettings.haloStrength; + result.defaultReflectionResolution = RenderSettings.defaultReflectionResolution; + result.defaultReflectionMode = RenderSettings.defaultReflectionMode; + result.reflectionBounces = RenderSettings.reflectionBounces; + result.reflectionIntensity = RenderSettings.reflectionIntensity; + result.customReflection = RenderSettings.customReflection; + result.ambientProbe = RenderSettings.ambientProbe; + result.sun = RenderSettings.sun; + result.skybox = RenderSettings.skybox; + result.subtractiveShadowColor = RenderSettings.subtractiveShadowColor; + result.flareStrength = RenderSettings.flareStrength; + result.ambientLight = RenderSettings.ambientLight; + result.ambientGroundColor = RenderSettings.ambientGroundColor; + result.ambientEquatorColor = RenderSettings.ambientEquatorColor; + result.ambientSkyColor = RenderSettings.ambientSkyColor; + result.ambientMode = RenderSettings.ambientMode; + result.fogDensity = RenderSettings.fogDensity; + result.fogColor = RenderSettings.fogColor; + result.fogMode = RenderSettings.fogMode; + result.fogEndDistance = RenderSettings.fogEndDistance; + result.fogStartDistance = RenderSettings.fogStartDistance; + result.fog = RenderSettings.fog; + result.ambientIntensity = RenderSettings.ambientIntensity; + result.flareFadeSpeed = RenderSettings.flareFadeSpeed; + return result; + } + + public void Apply() + { + RenderSettings.haloStrength = haloStrength; + RenderSettings.defaultReflectionResolution = defaultReflectionResolution; + RenderSettings.defaultReflectionMode = defaultReflectionMode; + RenderSettings.reflectionBounces = reflectionBounces; + RenderSettings.reflectionIntensity = reflectionIntensity; + RenderSettings.customReflection = customReflection; + RenderSettings.ambientProbe = ambientProbe; + RenderSettings.sun = sun; + RenderSettings.skybox = skybox; + RenderSettings.subtractiveShadowColor = subtractiveShadowColor; + RenderSettings.flareStrength = flareStrength; + RenderSettings.ambientLight = ambientLight; + RenderSettings.ambientGroundColor = ambientGroundColor; + RenderSettings.ambientEquatorColor = ambientEquatorColor; + RenderSettings.ambientSkyColor = ambientSkyColor; + RenderSettings.ambientMode = ambientMode; + RenderSettings.fogDensity = fogDensity; + RenderSettings.fogColor = fogColor; + RenderSettings.fogMode = fogMode; + RenderSettings.fogEndDistance = fogEndDistance; + RenderSettings.fogStartDistance = fogStartDistance; + RenderSettings.fog = fog; + RenderSettings.ambientIntensity = ambientIntensity; + RenderSettings.flareFadeSpeed = flareFadeSpeed; + } +} diff --git a/ilspy_dump/ror2_csproj/RendererSetMaterialsExtension.cs b/ilspy_dump/ror2_csproj/RendererSetMaterialsExtension.cs new file mode 100644 index 0000000..8ee8595 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RendererSetMaterialsExtension.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public static class RendererSetMaterialsExtension +{ + private static Material[][] sharedMaterialArrays; + + private static void InitSharedMaterialsArrays(int maxMaterials) + { + sharedMaterialArrays = new Material[maxMaterials + 1][]; + if (maxMaterials > 0) + { + sharedMaterialArrays[0] = Array.Empty(); + for (int i = 1; i < sharedMaterialArrays.Length; i++) + { + sharedMaterialArrays[i] = new Material[i]; + } + } + } + + static RendererSetMaterialsExtension() + { + InitSharedMaterialsArrays(16); + } + + public static void SetSharedMaterials(this Renderer renderer, Material[] sharedMaterials, int count) + { + if (sharedMaterialArrays.Length < count) + { + InitSharedMaterialsArrays(count); + } + Material[] array = sharedMaterialArrays[count]; + Array.Copy(sharedMaterials, array, count); + renderer.sharedMaterials = array; + Array.Clear(array, 0, count); + } + + public static void SetSharedMaterials(this Renderer renderer, List sharedMaterials) + { + int count = sharedMaterials.Count; + if (sharedMaterialArrays.Length < count) + { + InitSharedMaterialsArrays(count); + } + Material[] array = sharedMaterialArrays[count]; + sharedMaterials.CopyTo(array, 0); + renderer.sharedMaterials = array; + Array.Clear(array, 0, count); + } + + public static void SetMaterials(this Renderer renderer, Material[] materials, int count) + { + if (sharedMaterialArrays.Length < count) + { + InitSharedMaterialsArrays(count); + } + Material[] array = sharedMaterialArrays[count]; + Array.Copy(materials, array, count); + renderer.materials = array; + Array.Clear(array, 0, count); + } + + public static void SetMaterials(this Renderer renderer, List materials) + { + int count = materials.Count; + if (sharedMaterialArrays.Length < count) + { + InitSharedMaterialsArrays(count); + } + Material[] array = sharedMaterialArrays[count]; + materials.CopyTo(array, 0); + renderer.materials = array; + Array.Clear(array, 0, count); + } +} diff --git a/ilspy_dump/ror2_csproj/RendererVisiblity.cs b/ilspy_dump/ror2_csproj/RendererVisiblity.cs new file mode 100644 index 0000000..1233e4e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RendererVisiblity.cs @@ -0,0 +1,102 @@ +using RoR2; +using UnityEngine; + +public class RendererVisiblity : MonoBehaviour +{ + public enum DistanceClass + { + Near, + Far, + VeryFar + } + + public CharacterModel parentModel; + + public DistanceClass approxDistance; + + public bool isVisible; + + [HideInInspector] + public Animator animatorToUpdateOnceWhenVisible; + + private float visualUpdateTimer; + + public bool shouldUpdateVisuals = true; + + public void CalcDistanceClass(float distanceSq) + { + if (distanceSq < 2500f) + { + approxDistance = DistanceClass.Near; + } + else if (distanceSq < 10000f) + { + approxDistance = DistanceClass.Far; + } + else + { + approxDistance = DistanceClass.VeryFar; + } + if (!isVisible) + { + visualUpdateTimer -= Time.deltaTime; + if (visualUpdateTimer < 0f) + { + visualUpdateTimer = 0.2f; + shouldUpdateVisuals = true; + } + else + { + shouldUpdateVisuals = false; + } + return; + } + switch (approxDistance) + { + case DistanceClass.Near: + shouldUpdateVisuals = true; + break; + case DistanceClass.Far: + visualUpdateTimer -= Time.deltaTime; + if (visualUpdateTimer < 0f) + { + visualUpdateTimer = 1f / 15f; + shouldUpdateVisuals = true; + } + else + { + shouldUpdateVisuals = false; + } + break; + case DistanceClass.VeryFar: + visualUpdateTimer -= Time.deltaTime; + if (visualUpdateTimer < 0f) + { + visualUpdateTimer = 2f / 15f; + shouldUpdateVisuals = true; + } + else + { + shouldUpdateVisuals = false; + } + break; + } + } + + private void OnBecameVisible() + { + parentModel.SetVisible(visible: true); + isVisible = true; + if ((bool)animatorToUpdateOnceWhenVisible) + { + animatorToUpdateOnceWhenVisible.Update(0f); + animatorToUpdateOnceWhenVisible = null; + } + } + + private void OnBecameInvisible() + { + parentModel.SetVisible(visible: false); + isVisible = false; + } +} diff --git a/ilspy_dump/ror2_csproj/ResourceAvailability.cs b/ilspy_dump/ror2_csproj/ResourceAvailability.cs new file mode 100644 index 0000000..e5d4f11 --- /dev/null +++ b/ilspy_dump/ror2_csproj/ResourceAvailability.cs @@ -0,0 +1,31 @@ +using System; +using JetBrains.Annotations; + +public struct ResourceAvailability +{ + public bool available { get; private set; } + + private event Action onAvailable; + + public void MakeAvailable() + { + if (!available) + { + available = true; + this.onAvailable?.Invoke(); + this.onAvailable = null; + } + } + + public void CallWhenAvailable([NotNull] Action callback) + { + if (available) + { + callback(); + } + else + { + onAvailable += callback; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RewiredConsts/Action.cs b/ilspy_dump/ror2_csproj/RewiredConsts/Action.cs new file mode 100644 index 0000000..d848dfb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RewiredConsts/Action.cs @@ -0,0 +1,111 @@ +using Rewired.Dev; + +namespace RewiredConsts; + +public static class Action +{ + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Move Horizontal")] + public const int MoveHorizontal = 0; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Move Vertical")] + public const int MoveVertical = 1; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Aim Horizontal Mouse")] + public const int AimHorizontalMouse = 2; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Aim Vertical Mouse")] + public const int AimVerticalMouse = 3; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Aim Horizontal Stick")] + public const int AimHorizontalStick = 16; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Aim Vertical Stick")] + public const int AimVerticalStick = 17; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Jump")] + public const int Jump = 4; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Sprint")] + public const int Sprint = 18; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Interact")] + public const int Interact = 5; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Activate Equipment")] + public const int Equipment = 6; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Primary Skill")] + public const int PrimarySkill = 7; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Secondary Skill")] + public const int SecondarySkill = 8; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Utility Skill")] + public const int UtilitySkill = 9; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Special Skill")] + public const int SpecialSkill = 10; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Start")] + public const int Start = 11; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Info")] + public const int Info = 19; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UIHorizontal")] + public const int UIHorizontal = 12; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UIVertical")] + public const int UIVertical = 13; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UISubmit")] + public const int UISubmit = 14; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UICancel")] + public const int UICancel = 15; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UI Left Mouse Button")] + public const int UILMB = 20; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UI Right Mouse Button")] + public const int UIRMB = 21; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UI Middle Mouse Button")] + public const int UIMMB = 22; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UICursorX")] + public const int UICursorX = 23; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UICursorY")] + public const int UICursorY = 24; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UIScrollWheel")] + public const int UIScrollWheel = 26; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Pause")] + public const int Pause = 25; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "Ping")] + public const int Ping = 28; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UITabLeft")] + public const int UITabLeft = 29; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UITabRight")] + public const int UITabRight = 30; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UISubmitAlt")] + public const int UISubmitAlt = 31; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UISubmenuLeft")] + public const int UISubmenuLeft = 32; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UISubmenuRight")] + public const int UISubmenuRight = 33; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UISubmenuUp")] + public const int UISubmenuUp = 34; + + [ActionIdFieldInfo(categoryName = "Default", friendlyName = "UISubmenuDown")] + public const int UISubmenuDown = 35; +} diff --git a/ilspy_dump/ror2_csproj/RewiredConsts/Category.cs b/ilspy_dump/ror2_csproj/RewiredConsts/Category.cs new file mode 100644 index 0000000..09db2d4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RewiredConsts/Category.cs @@ -0,0 +1,8 @@ +namespace RewiredConsts; + +public static class Category +{ + public const int Default = 0; + + public const int UI = 2; +} diff --git a/ilspy_dump/ror2_csproj/RewiredConsts/CustomController.cs b/ilspy_dump/ror2_csproj/RewiredConsts/CustomController.cs new file mode 100644 index 0000000..362cffa --- /dev/null +++ b/ilspy_dump/ror2_csproj/RewiredConsts/CustomController.cs @@ -0,0 +1,5 @@ +namespace RewiredConsts; + +public static class CustomController +{ +} diff --git a/ilspy_dump/ror2_csproj/RewiredConsts/Layout.cs b/ilspy_dump/ror2_csproj/RewiredConsts/Layout.cs new file mode 100644 index 0000000..b1f8bac --- /dev/null +++ b/ilspy_dump/ror2_csproj/RewiredConsts/Layout.cs @@ -0,0 +1,26 @@ +namespace RewiredConsts; + +public static class Layout +{ + public static class Joystick + { + public const int Default = 0; + + public const int Default_JP = 1; + } + + public static class Keyboard + { + public const int Default = 0; + } + + public static class Mouse + { + public const int Default = 0; + } + + public static class CustomController + { + public const int Default = 0; + } +} diff --git a/ilspy_dump/ror2_csproj/RewiredConsts/Player.cs b/ilspy_dump/ror2_csproj/RewiredConsts/Player.cs new file mode 100644 index 0000000..d90eb23 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RewiredConsts/Player.cs @@ -0,0 +1,27 @@ +using Rewired.Dev; + +namespace RewiredConsts; + +public static class Player +{ + [PlayerIdFieldInfo(friendlyName = "System")] + public const int System = 9999999; + + [PlayerIdFieldInfo(friendlyName = "PlayerMain")] + public const int PlayerMain = 0; + + [PlayerIdFieldInfo(friendlyName = "Player1")] + public const int Player1 = 1; + + [PlayerIdFieldInfo(friendlyName = "Player2")] + public const int Player2 = 2; + + [PlayerIdFieldInfo(friendlyName = "Player3")] + public const int Player3 = 3; + + [PlayerIdFieldInfo(friendlyName = "Player4")] + public const int Player4 = 4; + + [PlayerIdFieldInfo(friendlyName = "Player5")] + public const int Player5 = 5; +} diff --git a/ilspy_dump/ror2_csproj/RewiredControllerSupport.cs b/ilspy_dump/ror2_csproj/RewiredControllerSupport.cs new file mode 100644 index 0000000..8b6a096 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RewiredControllerSupport.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class RewiredControllerSupport : MonoBehaviour +{ +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/BaseObtainArtifactAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/BaseObtainArtifactAchievement.cs new file mode 100644 index 0000000..bf1ba58 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/BaseObtainArtifactAchievement.cs @@ -0,0 +1,34 @@ +namespace RoR2.Achievements.Artifacts; + +public abstract class BaseObtainArtifactAchievement : BaseAchievement +{ + private UnlockableDef unlockableDef; + + protected abstract ArtifactDef artifactDef { get; } + + public override void OnInstall() + { + base.OnInstall(); + unlockableDef = artifactDef.unlockableDef; + UserProfile.onUnlockableGranted += OnUnlockableGranted; + if ((object)unlockableDef != null && base.userProfile.HasUnlockable(unlockableDef)) + { + Grant(); + } + } + + public override void OnUninstall() + { + UserProfile.onUnlockableGranted -= OnUnlockableGranted; + unlockableDef = null; + base.OnUninstall(); + } + + private void OnUnlockableGranted(UserProfile userProfile, UnlockableDef unlockableDef) + { + if ((object)unlockableDef == this.unlockableDef) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactAchievement.cs new file mode 100644 index 0000000..e679276 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactEliteOnly", "Artifacts.EliteOnly", null, 3u, null)] +public class ObtainArtifactAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.eliteOnlyArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactBombAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactBombAchievement.cs new file mode 100644 index 0000000..24eea1b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactBombAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactBomb", "Artifacts.Bomb", null, 3u, null)] +public class ObtainArtifactBombAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.bombArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactCommandAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactCommandAchievement.cs new file mode 100644 index 0000000..4084ebe --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactCommandAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactCommand", "Artifacts.Command", null, 3u, null)] +public class ObtainArtifactCommandAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.commandArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactDelusionAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactDelusionAchievement.cs new file mode 100644 index 0000000..c22afc4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactDelusionAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactDelusion", "Artifacts.Delusion", null, 2u, null)] +public class ObtainArtifactDelusionAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => CU8Content.Artifacts.Delusion; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactDevotionAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactDevotionAchievement.cs new file mode 100644 index 0000000..b5d73fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactDevotionAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactDevotion", "Artifacts.Devotion", null, 2u, null)] +public class ObtainArtifactDevotionAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => CU8Content.Artifacts.Devotion; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactEnigmaAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactEnigmaAchievement.cs new file mode 100644 index 0000000..1a82ab1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactEnigmaAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactEnigma", "Artifacts.Enigma", null, 3u, null)] +public class ObtainArtifactEnigmaAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.enigmaArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactFriendlyFireAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactFriendlyFireAchievement.cs new file mode 100644 index 0000000..18fc1e4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactFriendlyFireAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactFriendlyFire", "Artifacts.FriendlyFire", null, 3u, null)] +public class ObtainArtifactFriendlyFireAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.friendlyFireArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactGlassAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactGlassAchievement.cs new file mode 100644 index 0000000..78ef30d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactGlassAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactGlass", "Artifacts.Glass", null, 3u, null)] +public class ObtainArtifactGlassAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.glassArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactMixEnemyAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactMixEnemyAchievement.cs new file mode 100644 index 0000000..b9ac1fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactMixEnemyAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactMixEnemy", "Artifacts.MixEnemy", null, 3u, null)] +public class ObtainArtifactMixEnemyAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.mixEnemyArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactMonsterTeamGainsItemsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactMonsterTeamGainsItemsAchievement.cs new file mode 100644 index 0000000..7baf535 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactMonsterTeamGainsItemsAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactMonsterTeamGainsItems", "Artifacts.MonsterTeamGainsItems", null, 3u, null)] +public class ObtainArtifactMonsterTeamGainsItemsAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.monsterTeamGainsItemsArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactRandomSurvivorOnRespawnAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactRandomSurvivorOnRespawnAchievement.cs new file mode 100644 index 0000000..35b45f6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactRandomSurvivorOnRespawnAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactRandomSurvivorOnRespawn", "Artifacts.RandomSurvivorOnRespawn", null, 3u, null)] +public class ObtainArtifactRandomSurvivorOnRespawnAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.randomSurvivorOnRespawnArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactRebirthAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactRebirthAchievement.cs new file mode 100644 index 0000000..1d1d294 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactRebirthAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactRebirth", "Artifacts.Rebirth", null, 2u, null)] +public class ObtainArtifactRebirthAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => DLC2Content.Artifacts.Rebirth; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSacrificeAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSacrificeAchievement.cs new file mode 100644 index 0000000..41fdee9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSacrificeAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactSacrifice", "Artifacts.Sacrifice", null, 3u, null)] +public class ObtainArtifactSacrificeAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.sacrificeArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactShadowCloneAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactShadowCloneAchievement.cs new file mode 100644 index 0000000..b0c82d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactShadowCloneAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactShadowClone", "Artifacts.ShadowClone", null, 3u, null)] +public class ObtainArtifactShadowCloneAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.shadowCloneArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSingleMonsterTypeAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSingleMonsterTypeAchievement.cs new file mode 100644 index 0000000..2c8e179 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSingleMonsterTypeAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactSingleMonsterType", "Artifacts.SingleMonsterType", null, 3u, null)] +public class ObtainArtifactSingleMonsterTypeAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.singleMonsterTypeArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSwarmsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSwarmsAchievement.cs new file mode 100644 index 0000000..5feae84 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactSwarmsAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactSwarms", "Artifacts.Swarms", null, 3u, null)] +public class ObtainArtifactSwarmsAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.swarmsArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactTeamDeathAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactTeamDeathAchievement.cs new file mode 100644 index 0000000..8af2cb2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactTeamDeathAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactTeamDeath", "Artifacts.TeamDeath", null, 3u, null)] +public class ObtainArtifactTeamDeathAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.teamDeathArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactWeakAssKneesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactWeakAssKneesAchievement.cs new file mode 100644 index 0000000..92df875 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactWeakAssKneesAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactWeakAssKnees", "Artifacts.WeakAssKnees", null, 3u, null)] +public class ObtainArtifactWeakAssKneesAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.weakAssKneesArtifactDef; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactWispOnDeathAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactWispOnDeathAchievement.cs new file mode 100644 index 0000000..fe974f2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Artifacts/ObtainArtifactWispOnDeathAchievement.cs @@ -0,0 +1,7 @@ +namespace RoR2.Achievements.Artifacts; + +[RegisterAchievement("ObtainArtifactWispOnDeath", "Artifacts.WispOnDeath", null, 3u, null)] +public class ObtainArtifactWispOnDeathAchievement : BaseObtainArtifactAchievement +{ + protected override ArtifactDef artifactDef => RoR2Content.Artifacts.wispOnDeath; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2ClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2ClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..a15cf98 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2ClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Bandit2; + +[RegisterAchievement("Bandit2ClearGameMonsoon", "Skins.Bandit2.Alt1", "CompleteThreeStages", 10u, null)] +public class Bandit2ClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("Bandit2Body"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2ConsecutiveResetAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2ConsecutiveResetAchievement.cs new file mode 100644 index 0000000..72f8730 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2ConsecutiveResetAchievement.cs @@ -0,0 +1,121 @@ +using Assets.RoR2.Scripts.Platform; +using RoR2.Skills; + +namespace RoR2.Achievements.Bandit2; + +[RegisterAchievement("Bandit2ConsecutiveReset", "Skills.Bandit2.Rifle", "CompleteThreeStages", 3u, typeof(Bandit2ConsecutiveResetServerAchievement))] +public class Bandit2ConsecutiveResetAchievement : BaseAchievement +{ + private class Bandit2ConsecutiveResetServerAchievement : BaseServerAchievement + { + private int progress; + + private SkillDef requiredSkillDef; + + private bool waitingForKill; + + private CharacterBody _trackedBody; + + private CharacterBody trackedBody + { + get + { + return _trackedBody; + } + set + { + if ((object)_trackedBody != value) + { + if ((object)_trackedBody != null) + { + _trackedBody.onSkillActivatedServer -= OnBodySKillActivatedServer; + } + _trackedBody = value; + if ((object)_trackedBody != null) + { + _trackedBody.onSkillActivatedServer += OnBodySKillActivatedServer; + progress = 0; + waitingForKill = false; + } + } + } + } + + private void OnBodySKillActivatedServer(GenericSkill skillSlot) + { + if ((object)skillSlot.skillDef == requiredSkillDef && (object)requiredSkillDef != null) + { + if (waitingForKill) + { + progress = 0; + } + waitingForKill = true; + } + } + + public override void OnInstall() + { + base.OnInstall(); + requiredSkillDef = SkillCatalog.GetSkillDef(SkillCatalog.FindSkillIndexByName("Bandit2.ResetRevolver")); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + RoR2Application.onFixedUpdate += FixedUpdate; + } + + public override void OnUninstall() + { + trackedBody = null; + RoR2Application.onFixedUpdate -= FixedUpdate; + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + base.OnUninstall(); + } + + private void FixedUpdate() + { + trackedBody = GetCurrentBody(); + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if ((DamageType)(damageReport.damageInfo.damageType & DamageType.ResetCooldownsOnKill) == DamageType.ResetCooldownsOnKill && !(damageReport.attackerBody == null) && (object)damageReport.attackerBody == trackedBody) + { + waitingForKill = false; + progress++; + if (progress >= requirement) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + } + + private static readonly int requirement = 15; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("Bandit2Body"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "Bandit2ConsecutiveReset"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2MeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2MeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..3686b32 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2MeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Bandit2; + +[RegisterAchievement("Bandit2ClearMeridianEvent", "Skins.Bandit2.Alt2", "CompleteThreeStages", 5u, typeof(Bandit2MeridianEventTriggerServerAchievement))] +public class Bandit2MeridianEventTriggerAchievement : BaseAchievement +{ + private class Bandit2MeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("Bandit2Body"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2RevolverFinaleAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2RevolverFinaleAchievement.cs new file mode 100644 index 0000000..beaa3a1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2RevolverFinaleAchievement.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; + +namespace RoR2.Achievements.Bandit2; + +[RegisterAchievement("Bandit2RevolverFinale", "Skills.Bandit2.SkullRevolver", "CompleteThreeStages", 3u, typeof(Bandit2RevolverFinaleServerAchievement))] +public class Bandit2RevolverFinaleAchievement : BaseAchievement +{ + private class Bandit2RevolverFinaleServerAchievement : BaseServerAchievement + { + private const float lastHitWindowSeconds = 0.1f; + + private List requiredVictimBodyIndices; + + private float lastHitTime; + + public override void OnInstall() + { + base.OnInstall(); + requiredVictimBodyIndices = new List(); + requiredVictimBodyIndices.Add(BodyCatalog.FindBodyIndex("BrotherHurtBody")); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + GlobalEventManager.onServerDamageDealt += OnServerDamageDealt; + lastHitTime = float.NegativeInfinity; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + GlobalEventManager.onServerDamageDealt -= OnServerDamageDealt; + base.OnUninstall(); + } + + private void OnServerDamageDealt(DamageReport damageReport) + { + if (DoesDamageQualify(damageReport) && !(damageReport.attackerMaster == null) && (object)serverAchievementTracker.networkUser.master == damageReport.attackerMaster && requiredVictimBodyIndices.Contains(damageReport.victimBodyIndex)) + { + lastHitTime = Run.FixedTimeStamp.now.t; + } + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if ((DoesDamageQualify(damageReport) || !(Run.FixedTimeStamp.now.t - lastHitTime > 0.1f)) && !(damageReport.attackerMaster == null) && (object)serverAchievementTracker.networkUser.master == damageReport.attackerMaster && requiredVictimBodyIndices.Contains(damageReport.victimBodyIndex)) + { + Grant(); + } + } + + private bool DoesDamageQualify(DamageReport damageReport) + { + return (DamageType)(damageReport.damageInfo.damageType & DamageType.ResetCooldownsOnKill) == DamageType.ResetCooldownsOnKill; + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("Bandit2Body"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2StackSuperBleedAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2StackSuperBleedAchievement.cs new file mode 100644 index 0000000..b308d25 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Bandit2/Bandit2StackSuperBleedAchievement.cs @@ -0,0 +1,61 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Bandit2; + +[RegisterAchievement("Bandit2StackSuperBleed", "Skills.Bandit2.SerratedShivs", "CompleteThreeStages", 3u, typeof(Bandit2StackSuperBleedServerAchievement))] +public class Bandit2StackSuperBleedAchievement : BaseAchievement +{ + private class Bandit2StackSuperBleedServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + base.OnUninstall(); + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if ((bool)damageReport.attackerBody && (object)damageReport.attackerBody == GetCurrentBody() && (bool)damageReport.victimBody && damageReport.victimBody.GetBuffCount(RoR2Content.Buffs.SuperBleed) >= requirement) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + + private static readonly int requirement = 20; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("Bandit2Body"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "Bandit2StackSuperBleed"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Captain/CaptainMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Captain/CaptainMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..d65b7a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Captain/CaptainMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Captain; + +[RegisterAchievement("CaptainClearMeridianEvent", "Skins.Captain.Alt2", "CompleteMainEnding", 5u, typeof(CaptainMeridianEventTriggerServerAchievement))] +public class CaptainMeridianEventTriggerAchievement : BaseAchievement +{ + private class CaptainMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CaptainBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Captain/CaptainSupplyDropFinaleAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Captain/CaptainSupplyDropFinaleAchievement.cs new file mode 100644 index 0000000..958a1ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Captain/CaptainSupplyDropFinaleAchievement.cs @@ -0,0 +1,73 @@ +namespace RoR2.Achievements.Captain; + +[RegisterAchievement("CaptainSupplyDropFinale", "Skills.Captain.UtilityAlt1", "CompleteMainEnding", 3u, typeof(CaptainSupplyDropFinaleServerAchievement))] +public class CaptainSupplyDropFinaleAchievement : BaseAchievement +{ + private class CaptainSupplyDropFinaleServerAchievement : BaseServerAchievement + { + private const float lastHitWindowSeconds = 0.1f; + + private BodyIndex requiredVictimBodyIndex; + + private float lastHitTime; + + public override void OnInstall() + { + base.OnInstall(); + requiredVictimBodyIndex = BodyCatalog.FindBodyIndex("BrotherHurtBody"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + GlobalEventManager.onServerDamageDealt += OnServerDamageDealt; + lastHitTime = float.NegativeInfinity; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + GlobalEventManager.onServerDamageDealt -= OnServerDamageDealt; + base.OnUninstall(); + } + + private void OnServerDamageDealt(DamageReport damageReport) + { + if (damageReport.victimBodyIndex == requiredVictimBodyIndex && DoesDamageQualify(damageReport) && (object)serverAchievementTracker.networkUser.master == damageReport.attackerMaster && (bool)damageReport.attackerMaster) + { + lastHitTime = Run.FixedTimeStamp.now.t; + } + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if (damageReport.victimBodyIndex == requiredVictimBodyIndex && (object)serverAchievementTracker.networkUser.master == damageReport.attackerMaster && (bool)damageReport.attackerMaster && (DoesDamageQualify(damageReport) || Run.FixedTimeStamp.now.t - lastHitTime <= 0.1f)) + { + Grant(); + } + } + + private bool DoesDamageQualify(DamageReport damageReport) + { + GenericDisplayNameProvider component = damageReport.damageInfo.inflictor.GetComponent(); + if ((bool)component && component.displayToken != null) + { + return component.displayToken.StartsWith("CAPTAIN_SUPPLY_"); + } + return false; + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CaptainBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ActivateChefAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ActivateChefAchievement.cs new file mode 100644 index 0000000..f251064 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ActivateChefAchievement.cs @@ -0,0 +1,40 @@ +namespace RoR2.Achievements.Chef; + +[RegisterAchievement("ActivateChef", "Characters.Chef", null, 3u, typeof(ActivateChefServerAchievement))] +public class ActivateChefAchievement : BaseAchievement +{ + private class ActivateChefServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + WokController.chefRecipeComplete += OnRecipeComplete; + } + + public override void OnUninstall() + { + base.OnInstall(); + WokController.chefRecipeComplete -= OnRecipeComplete; + } + + private void OnRecipeComplete(Interactor interactor) + { + CharacterBody currentBody = serverAchievementTracker.networkUser.GetCurrentBody(); + if ((bool)currentBody && currentBody.GetComponent() == interactor) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ChefAlternateSpecialBarbecueBison.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ChefAlternateSpecialBarbecueBison.cs new file mode 100644 index 0000000..53c3aa4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ChefAlternateSpecialBarbecueBison.cs @@ -0,0 +1,71 @@ +using System; +using RoR2.Stats; + +namespace RoR2.Achievements.Chef; + +[RegisterAchievement("BarbecueQuantityBisonInRun", "Skills.Chef.YesChef", "ActivateChef", 3u, typeof(ChefAlternateSpecialBarbecueBisonServer))] +public class ChefAlternateSpecialBarbecueBison : BaseAchievement +{ + private class ChefAlternateSpecialBarbecueBisonServer : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if ((object)damageReport.attackerMaster == base.networkUser.master && (object)damageReport.attackerMaster != null && damageReport.victimBody.baseNameToken == "BISON_BODY_NAME" && damageReport.victimBody.HasBuff(DLC2Content.Buffs.CookingFlambe) && damageReport.victimBody.HasBuff(DLC2Content.Buffs.CookingRoasted)) + { + PlayerStatsComponent masterPlayerStatsComponent = base.networkUser.masterPlayerStatsComponent; + if ((bool)masterPlayerStatsComponent) + { + masterPlayerStatsComponent.currentStats.PushStatValue(StatDef.chefAlternateSpecialBarbecueBisonAchievementProgress, 1uL); + } + } + } + } + + private ulong requirement = 10uL; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ChefBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(Check)); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(Check)); + } + + private void Check() + { + if (base.userProfile.statSheet.GetStatValueULong(StatDef.chefAlternateSpecialBarbecueBisonAchievementProgress) >= requirement) + { + Grant(); + } + } + + public override float ProgressForAchievement() + { + return (float)base.userProfile.statSheet.GetStatValueULong(StatDef.chefAlternateSpecialBarbecueBisonAchievementProgress) / (float)requirement; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ChefClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ChefClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..8eb4bac --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Chef/ChefClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Chef; + +[RegisterAchievement("ChefClearGameMonsoon", "Skins.Chef.Alt1", "ActivateChef", 10u, null)] +public class ChefClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ChefBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CaptainClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CaptainClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..fe73e0c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CaptainClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CaptainClearGameMonsoon", "Skins.Captain.Alt1", "CompleteMainEnding", 10u, null)] +public class CaptainClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CaptainBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..3bd07c0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CommandoClearGameMonsoon", "Skins.Commando.Alt1", null, 10u, null)] +public class CommandoClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CommandoBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoFastFirstStageClearAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoFastFirstStageClearAchievement.cs new file mode 100644 index 0000000..933ef03 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoFastFirstStageClearAchievement.cs @@ -0,0 +1,32 @@ +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CommandoFastFirstStageClear", "Skills.Commando.SlideJet", null, 3u, null)] +public class CommandoFastFirstStageClearAchievement : BaseAchievement +{ + private static readonly float timeRequirement = 300f; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CommandoBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterChargedGlobal; + } + + private void OnTeleporterChargedGlobal(TeleporterInteraction teleporterInteraction) + { + if (Run.instance.GetRunStopwatch() < timeRequirement && Run.instance.stageClearCount == 0 && base.isUserAlive) + { + Grant(); + } + } + + protected override void OnBodyRequirementBroken() + { + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterChargedGlobal; + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoKillOverloadingWormAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoKillOverloadingWormAchievement.cs new file mode 100644 index 0000000..7ef4688 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoKillOverloadingWormAchievement.cs @@ -0,0 +1,50 @@ +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CommandoKillOverloadingWorm", "Skills.Commando.FireShotgunBlast", null, 3u, typeof(CommandoKillOverloadingWormServerAchievement))] +public class CommandoKillOverloadingWormAchievement : BaseAchievement +{ + public class CommandoKillOverloadingWormServerAchievement : BaseServerAchievement + { + private BodyIndex overloadingWormBodyIndex; + + public override void OnInstall() + { + base.OnInstall(); + overloadingWormBodyIndex = BodyCatalog.FindBodyIndex("ElectricWormBody"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if ((bool)damageReport.victimBody && damageReport.victimBody.bodyIndex == overloadingWormBodyIndex && IsCurrentBody(damageReport.damageInfo.attacker)) + { + Grant(); + } + } + } + + private int commandoBodyIndex; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CommandoBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..b05340b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CommandoClearMeridianEvent", "Skins.Commando.Alt2", null, 5u, typeof(CommandoMeridianEventTriggerServerAchievement))] +public class CommandoMeridianEventTriggerAchievement : BaseAchievement +{ + private class CommandoMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CommandoBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoNonLunarEnduranceAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoNonLunarEnduranceAchievement.cs new file mode 100644 index 0000000..00aa8c6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CommandoNonLunarEnduranceAchievement.cs @@ -0,0 +1,111 @@ +using System; +using Assets.RoR2.Scripts.Platform; +using RoR2.Stats; + +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CommandoNonLunarEndurance", "Skills.Commando.ThrowGrenade", null, 3u, null)] +public class CommandoNonLunarEnduranceAchievement : BaseAchievement +{ + private static readonly ulong requirement = 20uL; + + private PlayerCharacterMasterController cachedMasterController; + + private PlayerStatsComponent cachedStatsComponent; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CommandoBody"); + } + + private static bool EverPickedUpLunarItems(StatSheet statSheet) + { + foreach (ItemIndex lunarItem in ItemCatalog.lunarItemList) + { + if (statSheet.GetStatValueULong(PerItemStatDef.totalCollected.FindStatDef(lunarItem)) != 0) + { + return true; + } + } + foreach (EquipmentIndex equipment in EquipmentCatalog.equipmentList) + { + if (EquipmentCatalog.GetEquipmentDef(equipment).isLunar && statSheet.GetStatValueDouble(PerEquipmentStatDef.totalTimeHeld.FindStatDef(equipment)) > 0.0) + { + return true; + } + } + return false; + } + + private void OnMasterChanged() + { + if (base.localUser != null) + { + SetMasterController(base.localUser.cachedMasterController); + } + } + + private void SetMasterController(PlayerCharacterMasterController playerCharacterMasterController) + { + if ((object)base.localUser.cachedMasterController == cachedMasterController) + { + return; + } + bool num = (object)cachedStatsComponent != null; + cachedMasterController = base.localUser.cachedMasterController; + cachedStatsComponent = (cachedMasterController ? cachedMasterController.GetComponent() : null); + bool flag = (object)cachedStatsComponent != null; + if (num != flag && base.userProfile != null) + { + if (flag) + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(OnStatsChanged)); + } + else + { + UserProfile obj2 = base.userProfile; + obj2.onStatsReceived = (Action)Delegate.Remove(obj2.onStatsReceived, new Action(OnStatsChanged)); + } + } + } + + private void OnStatsChanged() + { + if ((object)cachedStatsComponent != null && requirement <= cachedStatsComponent.currentStats.GetStatValueULong(StatDef.totalStagesCompleted)) + { + if (EverPickedUpLunarItems(cachedStatsComponent.currentStats)) + { + SetMasterController(null); + return; + } + Grant(); + TryToCompleteActivity(); + } + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + base.localUser.onMasterChanged += OnMasterChanged; + OnMasterChanged(); + } + + protected override void OnBodyRequirementBroken() + { + base.localUser.onMasterChanged -= OnMasterChanged; + SetMasterController(null); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "CommandoNonLunarEndurance"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CrocoClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CrocoClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..2797404 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Commando/CrocoClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Commando; + +[RegisterAchievement("CrocoClearGameMonsoon", "Skins.Croco.Alt1", "BeatArena", 10u, null)] +public class CrocoClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CrocoBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoKillScavengerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoKillScavengerAchievement.cs new file mode 100644 index 0000000..33b396b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoKillScavengerAchievement.cs @@ -0,0 +1,48 @@ +namespace RoR2.Achievements.Croco; + +[RegisterAchievement("CrocoKillScavenger", "Skills.Croco.CrocoBite", "BeatArena", 3u, typeof(CrocoKillScavengerServerAchievement))] +public class CrocoKillScavengerAchievement : BaseAchievement +{ + private class CrocoKillScavengerServerAchievement : BaseServerAchievement + { + private BodyIndex requiredVictimBodyIndex; + + public override void OnInstall() + { + base.OnInstall(); + requiredVictimBodyIndex = BodyCatalog.FindBodyIndex("ScavBody"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + base.OnUninstall(); + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if (damageReport.victimBodyIndex == requiredVictimBodyIndex && serverAchievementTracker.networkUser.master == damageReport.attackerMaster) + { + Grant(); + } + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CrocoBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoKillWeakEnemiesMilestoneAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoKillWeakEnemiesMilestoneAchievement.cs new file mode 100644 index 0000000..647eca8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoKillWeakEnemiesMilestoneAchievement.cs @@ -0,0 +1,22 @@ +using Assets.RoR2.Scripts.Platform; +using RoR2.Stats; + +namespace RoR2.Achievements.Croco; + +[RegisterAchievement("CrocoKillWeakEnemiesMilestone", "Skills.Croco.PassivePoisonLethal", "BeatArena", 3u, null)] +public class CrocoKillWeakEnemiesMilestoneAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalCrocoWeakEnemyKills; + + protected override ulong statRequirement => 50uL; + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "CrocoKillWeakEnemiesMilestone"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..d487e57 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Croco; + +[RegisterAchievement("CrocoClearMeridianEvent", "Skins.Croco.Alt2", "BeatArena", 5u, typeof(CrocoMeridianEventTriggerServerAchievement))] +public class CrocoMeridianEventTriggerAchievement : BaseAchievement +{ + private class CrocoMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CrocoBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoTotalInfectionsMilestoneAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoTotalInfectionsMilestoneAchievement.cs new file mode 100644 index 0000000..c2279c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Croco/CrocoTotalInfectionsMilestoneAchievement.cs @@ -0,0 +1,22 @@ +using Assets.RoR2.Scripts.Platform; +using RoR2.Stats; + +namespace RoR2.Achievements.Croco; + +[RegisterAchievement("CrocoTotalInfectionsMilestone", "Skills.Croco.ChainableLeap", "BeatArena", 3u, null)] +public class CrocoTotalInfectionsMilestoneAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalCrocoInfectionsInflicted; + + protected override ulong statRequirement => 1000uL; + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "CrocoTotalInfectionsMilestone"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiArmyAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiArmyAchievement.cs new file mode 100644 index 0000000..721239d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiArmyAchievement.cs @@ -0,0 +1,73 @@ +using Assets.RoR2.Scripts.Platform; +using UnityEngine.Networking; + +namespace RoR2.Achievements.Engi; + +[RegisterAchievement("EngiArmy", "Skills.Engi.WalkerTurret", "Complete30StagesCareer", 3u, null)] +public class EngiArmyAchievement : BaseAchievement +{ + private static readonly int requirement = 12; + + private ToggleAction monitorMinions; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("EngiBody"); + } + + private void SubscribeToMinionChanges() + { + MinionOwnership.onMinionGroupChangedGlobal += OnMinionGroupChangedGlobal; + } + + private void UnsubscribeFromMinionChanges() + { + MinionOwnership.onMinionGroupChangedGlobal -= OnMinionGroupChangedGlobal; + } + + private void OnMinionGroupChangedGlobal(MinionOwnership minion) + { + if (requirement > (minion.group?.memberCount ?? 0)) + { + return; + } + CharacterMaster master = base.localUser.cachedMasterController.master; + if ((bool)master) + { + NetworkInstanceId netId = master.netId; + if (minion.group.ownerId == netId) + { + Grant(); + TryToCompleteActivity(); + } + } + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "EngiArmy"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } + + public override void OnInstall() + { + base.OnInstall(); + monitorMinions = new ToggleAction(SubscribeToMinionChanges, UnsubscribeFromMinionChanges); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + monitorMinions.SetActive(newActive: true); + } + + protected override void OnBodyRequirementBroken() + { + monitorMinions.SetActive(newActive: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..94323e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Engi; + +[RegisterAchievement("EngiClearGameMonsoon", "Skins.Engi.Alt1", "Complete30StagesCareer", 10u, null)] +public class EngiClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("EngiBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiClearTeleporterWithZeroMonstersAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiClearTeleporterWithZeroMonstersAchievement.cs new file mode 100644 index 0000000..c4c524f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiClearTeleporterWithZeroMonstersAchievement.cs @@ -0,0 +1,51 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Engi; + +[RegisterAchievement("EngiClearTeleporterWithZeroMonsters", "Skills.Engi.Harpoon", "Complete30StagesCareer", 3u, null)] +public class EngiClearTeleporterWithZeroMonstersAchievement : BaseAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("EngiBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterChargedGlobal; + } + + protected override void OnBodyRequirementBroken() + { + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterChargedGlobal; + base.OnBodyRequirementBroken(); + } + + private void OnTeleporterChargedGlobal(TeleporterInteraction teleporterInteraction) + { + if (!base.isUserAlive) + { + return; + } + foreach (TeamComponent teamMember in TeamComponent.GetTeamMembers(TeamIndex.Monster)) + { + if (teamMember.body.healthComponent.alive) + { + return; + } + } + Grant(); + TryToCompleteActivity(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "EngiClearTeleporterWithZeroMonsters"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiKillBossQuickAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiKillBossQuickAchievement.cs new file mode 100644 index 0000000..e6fda4b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiKillBossQuickAchievement.cs @@ -0,0 +1,60 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Engi; + +[RegisterAchievement("EngiKillBossQuick", "Skills.Engi.SpiderMine", "Complete30StagesCareer", 3u, typeof(EngiKillBossQuickServerAchievement))] +public class EngiKillBossQuickAchievement : BaseAchievement +{ + private class EngiKillBossQuickServerAchievement : BaseServerAchievement + { + private const float requirement = 5f; + + public override void OnInstall() + { + base.OnInstall(); + BossGroup.onBossGroupDefeatedServer += OnBossGroupDefeatedServer; + } + + public override void OnUninstall() + { + BossGroup.onBossGroupDefeatedServer -= OnBossGroupDefeatedServer; + base.OnUninstall(); + } + + private void OnBossGroupDefeatedServer(BossGroup bossGroup) + { + if (bossGroup.fixedTimeSinceEnabled <= 5f) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("EngiBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "EngiKillBossQuick"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..4eb8a9e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Engi/EngiMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Engi; + +[RegisterAchievement("EngiClearMeridianEvent", "Skins.Engi.Alt2", "Complete30StagesCareer", 5u, typeof(EngiMeridianEventTriggerServerAchievement))] +public class EngiMeridianEventTriggerAchievement : BaseAchievement +{ + private class EngiMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("EngiBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.FalseSon/FalseSonClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.FalseSon/FalseSonClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..d3a86fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.FalseSon/FalseSonClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.FalseSon; + +[RegisterAchievement("FalseSonClearGameMonsoon", "Skins.FalseSon.Alt1", "UnlockFalseSon", 10u, null)] +public class FalseSonClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("FalseSonBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.FalseSon/FalseSonLaserMultiKill.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.FalseSon/FalseSonLaserMultiKill.cs new file mode 100644 index 0000000..a742af7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.FalseSon/FalseSonLaserMultiKill.cs @@ -0,0 +1,68 @@ +using EntityStates.FalseSon; + +namespace RoR2.Achievements.FalseSon; + +[RegisterAchievement("FalseSonLaserMultiKill", "Skills.FalseSon.LaserBurst", "UnlockFalseSon", 3u, typeof(FalseSonLaserMultiKillServerAchievement))] +public class FalseSonLaserMultiKill : BaseAchievement +{ + private class FalseSonLaserMultiKillServerAchievement : BaseServerAchievement + { + private int killCount; + + private float localLaserDuration; + + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + LaserFatherCharged.laserTracking += TrackLaserActivation; + } + + public override void OnUninstall() + { + LaserFatherCharged.laserTracking -= TrackLaserActivation; + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void TrackLaserActivation(float laserDuration) + { + localLaserDuration = laserDuration; + if (localLaserDuration <= 0f) + { + killCount = 0; + } + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if (localLaserDuration > 0f && (object)damageReport.attackerMaster != null && (object)damageReport.attackerMaster == base.networkUser.master && (bool)damageReport.victimBody && (damageReport.victimBody.bodyFlags & CharacterBody.BodyFlags.Masterless) == 0) + { + killCount++; + if (requirement <= killCount) + { + Grant(); + } + } + } + } + + private static readonly int requirement = 15; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("FalseSonBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressAllGlaiveBouncesKillAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressAllGlaiveBouncesKillAchievement.cs new file mode 100644 index 0000000..3d5adce --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressAllGlaiveBouncesKillAchievement.cs @@ -0,0 +1,61 @@ +using Assets.RoR2.Scripts.Platform; +using RoR2.Orbs; + +namespace RoR2.Achievements.Huntress; + +[RegisterAchievement("HuntressAllGlaiveBouncesKill", "Skills.Huntress.FlurryArrow", null, 3u, typeof(HuntressAllGlaiveBouncesKillServerAchievement))] +public class HuntressAllGlaiveBouncesKillAchievement : BaseAchievement +{ + private class HuntressAllGlaiveBouncesKillServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + LightningOrb.onLightningOrbKilledOnAllBounces += OnLightningOrbKilledOnAllBounces; + } + + private void OnLightningOrbKilledOnAllBounces(LightningOrb lightningOrb) + { + CharacterBody currentBody = base.networkUser.GetCurrentBody(); + if ((bool)currentBody && lightningOrb.attacker == currentBody.gameObject && lightningOrb.lightningType == LightningOrb.LightningType.HuntressGlaive) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + + public override void OnUninstall() + { + LightningOrb.onLightningOrbKilledOnAllBounces -= OnLightningOrbKilledOnAllBounces; + base.OnUninstall(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("HuntressBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "HuntressAllGlaiveBouncesKill"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..7cc8a11 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Huntress; + +[RegisterAchievement("HuntressClearGameMonsoon", "Skins.Huntress.Alt1", null, 10u, null)] +public class HuntressClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("HuntressBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressCollectCrowbarsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressCollectCrowbarsAchievement.cs new file mode 100644 index 0000000..6ae32a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressCollectCrowbarsAchievement.cs @@ -0,0 +1,88 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Huntress; + +[RegisterAchievement("HuntressCollectCrowbars", "Skills.Huntress.MiniBlink", null, 3u, null)] +public class HuntressCollectCrowbarsAchievement : BaseAchievement +{ + private Inventory currentInventory; + + private static readonly int requirement = 12; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("HuntressBody"); + } + + public override void OnInstall() + { + base.OnInstall(); + } + + public override void OnUninstall() + { + SetCurrentInventory(null); + base.OnUninstall(); + } + + private void UpdateInventory() + { + Inventory inventory = null; + if ((bool)base.localUser.cachedMasterController) + { + inventory = base.localUser.cachedMasterController.master.inventory; + } + SetCurrentInventory(inventory); + } + + private void SetCurrentInventory(Inventory newInventory) + { + if ((object)currentInventory != newInventory) + { + if ((object)currentInventory != null) + { + currentInventory.onInventoryChanged -= OnInventoryChanged; + } + currentInventory = newInventory; + if ((object)currentInventory != null) + { + currentInventory.onInventoryChanged += OnInventoryChanged; + OnInventoryChanged(); + } + } + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + base.localUser.onMasterChanged += UpdateInventory; + UpdateInventory(); + } + + protected override void OnBodyRequirementBroken() + { + base.localUser.onMasterChanged -= UpdateInventory; + SetCurrentInventory(null); + base.OnBodyRequirementBroken(); + } + + private void OnInventoryChanged() + { + if (requirement <= currentInventory.GetItemCount(RoR2Content.Items.Crowbar)) + { + Grant(); + TryToCompleteActivity(); + } + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "HuntressCollectCrowbars"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressMaintainFullHealthOnFrozenWallAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressMaintainFullHealthOnFrozenWallAchievement.cs new file mode 100644 index 0000000..f040d49 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressMaintainFullHealthOnFrozenWallAchievement.cs @@ -0,0 +1,119 @@ +using System; + +namespace RoR2.Achievements.Huntress; + +[RegisterAchievement("HuntressMaintainFullHealthOnFrozenWall", "Skills.Huntress.Snipe", null, 3u, null)] +public class HuntressMaintainFullHealthOnFrozenWallAchievement : BaseAchievement +{ + private static readonly string[] requiredScenes = new string[2] { "frozenwall", "wispgraveyard" }; + + private HealthComponent healthComponent; + + private bool failed; + + private bool sceneOk; + + private bool characterOk; + + private ToggleAction healthCheck; + + private ToggleAction teleporterCheck; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("HuntressBody"); + } + + private void SubscribeHealthCheck() + { + RoR2Application.onFixedUpdate += CheckHealth; + } + + private void UnsubscribeHealthCheck() + { + RoR2Application.onFixedUpdate -= CheckHealth; + } + + private void SubscribeTeleporterCheck() + { + TeleporterInteraction.onTeleporterChargedGlobal += CheckTeleporter; + } + + private void UnsubscribeTeleporterCheck() + { + TeleporterInteraction.onTeleporterChargedGlobal -= CheckTeleporter; + } + + private void CheckTeleporter(TeleporterInteraction teleporterInteraction) + { + if (sceneOk && characterOk && !failed) + { + Grant(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + healthCheck = new ToggleAction(SubscribeHealthCheck, UnsubscribeHealthCheck); + teleporterCheck = new ToggleAction(SubscribeTeleporterCheck, UnsubscribeTeleporterCheck); + SceneCatalog.onMostRecentSceneDefChanged += OnMostRecentSceneDefChanged; + base.localUser.onBodyChanged += OnBodyChanged; + } + + public override void OnUninstall() + { + base.localUser.onBodyChanged -= OnBodyChanged; + SceneCatalog.onMostRecentSceneDefChanged -= OnMostRecentSceneDefChanged; + healthCheck.Dispose(); + teleporterCheck.Dispose(); + base.OnUninstall(); + } + + private void OnBodyChanged() + { + if (sceneOk && characterOk && !failed && (bool)base.localUser.cachedBody) + { + healthComponent = base.localUser.cachedBody.healthComponent; + healthCheck.SetActive(newActive: true); + teleporterCheck.SetActive(newActive: true); + } + } + + private void OnMostRecentSceneDefChanged(SceneDef sceneDef) + { + sceneOk = Array.IndexOf(requiredScenes, sceneDef.baseSceneName) != -1; + if (sceneOk) + { + failed = false; + } + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + characterOk = true; + } + + protected override void OnBodyRequirementBroken() + { + characterOk = false; + Fail(); + base.OnBodyRequirementBroken(); + } + + private void Fail() + { + failed = true; + healthCheck.SetActive(newActive: false); + teleporterCheck.SetActive(newActive: false); + } + + private void CheckHealth() + { + if ((bool)healthComponent && healthComponent.combinedHealth < healthComponent.fullCombinedHealth) + { + Fail(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..eb95b32 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Huntress/HuntressMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Huntress; + +[RegisterAchievement("HuntressClearMeridianEvent", "Skins.Huntress.Alt2", null, 5u, typeof(HuntressMeridianEventTriggerServerAchievement))] +public class HuntressMeridianEventTriggerAchievement : BaseAchievement +{ + private class HuntressMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("HuntressBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..83d96e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Loader; + +[RegisterAchievement("LoaderClearGameMonsoon", "Skins.Loader.Alt1", "DefeatSuperRoboBallBoss", 10u, null)] +public class LoaderClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("LoaderBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..cf66188 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Loader; + +[RegisterAchievement("LoaderClearMeridianEvent", "Skins.Loader.Alt2", "DefeatSuperRoboBallBoss", 5u, typeof(LoaderMeridianEventTriggerServerAchievement))] +public class LoaderMeridianEventTriggerAchievement : BaseAchievement +{ + private class LoaderMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("LoaderBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderSpeedRunAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderSpeedRunAchievement.cs new file mode 100644 index 0000000..e06aa35 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Loader/LoaderSpeedRunAchievement.cs @@ -0,0 +1,40 @@ +namespace RoR2.Achievements.Loader; + +[RegisterAchievement("LoaderSpeedRun", "Skills.Loader.YankHook", "DefeatSuperRoboBallBoss", 3u, null)] +public class LoaderSpeedRunAchievement : BaseAchievement +{ + private SceneDef requiredSceneDef; + + private static readonly float requirement = 1500f; + + public override void OnInstall() + { + base.OnInstall(); + requiredSceneDef = SceneCatalog.GetSceneDefFromSceneName("mysteryspace"); + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("LoaderBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SceneCatalog.onMostRecentSceneDefChanged += OnMostRecentSceneDefChanged; + } + + private void OnMostRecentSceneDefChanged(SceneDef sceneDef) + { + if (sceneDef == requiredSceneDef && Run.instance.GetRunStopwatch() <= requirement) + { + Grant(); + } + } + + protected override void OnBodyRequirementBroken() + { + SceneCatalog.onMostRecentSceneDefChanged -= OnMostRecentSceneDefChanged; + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageAirborneMultiKillAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageAirborneMultiKillAchievement.cs new file mode 100644 index 0000000..0391aa4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageAirborneMultiKillAchievement.cs @@ -0,0 +1,86 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Mage; + +[RegisterAchievement("MageAirborneMultiKill", "Skills.Mage.FlyUp", "FreeMage", 3u, typeof(MageAirborneMultiKillServerAchievement))] +public class MageAirborneMultiKillAchievement : BaseAchievement +{ + private class MageAirborneMultiKillServerAchievement : BaseServerAchievement + { + private int killCount; + + public override void OnInstall() + { + base.OnInstall(); + RoR2Application.onFixedUpdate += OnFixedUpdate; + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + RoR2Application.onFixedUpdate -= OnFixedUpdate; + base.OnUninstall(); + } + + private bool CharacterIsInAir() + { + CharacterBody currentBody = base.networkUser.GetCurrentBody(); + if ((bool)currentBody && (bool)currentBody.characterMotor) + { + return !currentBody.characterMotor.isGrounded; + } + return false; + } + + private void OnFixedUpdate() + { + if (!CharacterIsInAir()) + { + killCount = 0; + } + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if ((object)damageReport.attackerMaster == base.networkUser.master && (object)damageReport.attackerMaster != null && CharacterIsInAir()) + { + killCount++; + if (requirement <= killCount) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + } + + private static readonly int requirement = 15; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MageBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "MageAirborneMultiKill"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..bcddade --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Mage; + +[RegisterAchievement("MageClearGameMonsoon", "Skins.Mage.Alt1", "FreeMage", 10u, null)] +public class MageClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MageBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageFastBossAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageFastBossAchievement.cs new file mode 100644 index 0000000..deeba4a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageFastBossAchievement.cs @@ -0,0 +1,124 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Mage; + +[RegisterAchievement("MageFastBoss", "Skills.Mage.IceBomb", "FreeMage", 3u, typeof(MageFastBossServerAchievement))] +public class MageFastBossAchievement : BaseAchievement +{ + private class MageFastBossServerAchievement : BaseServerAchievement + { + private ToggleAction listenForBossDamage; + + private ToggleAction listenForBossDefeated; + + private Run.FixedTimeStamp expirationTimeStamp; + + private void OnBossDamageFirstTaken() + { + expirationTimeStamp = Run.FixedTimeStamp.now + window; + listenForBossDamage.SetActive(newActive: false); + listenForBossDefeated.SetActive(newActive: true); + } + + public override void OnInstall() + { + base.OnInstall(); + listenForBossDamage = new ToggleAction(delegate + { + GlobalEventManager.onServerDamageDealt += OnServerDamageDealt; + }, delegate + { + GlobalEventManager.onServerDamageDealt -= OnServerDamageDealt; + }); + listenForBossDefeated = new ToggleAction(delegate + { + BossGroup.onBossGroupDefeatedServer += OnBossGroupDefeatedServer; + }, delegate + { + BossGroup.onBossGroupDefeatedServer -= OnBossGroupDefeatedServer; + }); + BossGroup.onBossGroupStartServer += OnBossGroupStartServer; + Run.onRunStartGlobal += OnRunStart; + Reset(); + } + + public override void OnUninstall() + { + BossGroup.onBossGroupStartServer -= OnBossGroupStartServer; + listenForBossDefeated.SetActive(newActive: false); + listenForBossDamage.SetActive(newActive: false); + base.OnUninstall(); + } + + private void OnRunStart(Run run) + { + Reset(); + } + + private void Reset() + { + expirationTimeStamp = Run.FixedTimeStamp.negativeInfinity; + listenForBossDefeated.SetActive(newActive: false); + listenForBossDamage.SetActive(newActive: false); + } + + private static bool BossGroupIsTeleporterBoss(BossGroup bossGroup) + { + return bossGroup.GetComponent(); + } + + private void OnBossGroupStartServer(BossGroup bossGroup) + { + if (BossGroupIsTeleporterBoss(bossGroup)) + { + listenForBossDamage.SetActive(newActive: true); + } + } + + private void OnServerDamageDealt(DamageReport damageReport) + { + if ((bool)damageReport.victimMaster && damageReport.victimMaster.isBoss) + { + OnBossDamageFirstTaken(); + } + } + + private void OnBossGroupDefeatedServer(BossGroup bossGroup) + { + if (BossGroupIsTeleporterBoss(bossGroup) && !expirationTimeStamp.hasPassed) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + + private static readonly float window = 1f; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MageBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "MageFastBoss"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..cc37e68 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Mage; + +[RegisterAchievement("MageClearMeridianEvent", "Skins.Mage.Alt2", "FreeMage", 5u, typeof(MageMeridianEventTriggerServerAchievement))] +public class MageMeridianEventTriggerAchievement : BaseAchievement +{ + private class MageMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MageBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMultiExecuteAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMultiExecuteAchievement.cs new file mode 100644 index 0000000..cef75c6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMultiExecuteAchievement.cs @@ -0,0 +1,58 @@ +namespace RoR2.Achievements.Mage; + +public class MageMultiExecuteAchievement : BaseAchievement +{ + private class MageMultiExecuteServerAchievement : BaseServerAchievement + { + private DoXInYSecondsTracker tracker; + + public override void OnInstall() + { + base.OnInstall(); + tracker = new DoXInYSecondsTracker(requirement, window); + Run.onRunStartGlobal += OnRunStart; + GlobalEventManager.onServerCharacterExecuted += OnServerCharacterExecuted; + } + + public override void OnUninstall() + { + Run.onRunStartGlobal -= OnRunStart; + GlobalEventManager.onServerCharacterExecuted -= OnServerCharacterExecuted; + base.OnUninstall(); + } + + private void OnRunStart(Run run) + { + tracker.Clear(); + } + + private void OnServerCharacterExecuted(DamageReport damageReport, float executionHealthLost) + { + if ((object)damageReport.attackerMaster == base.networkUser.master && (object)base.networkUser.master != null && tracker.Push(Run.FixedTimeStamp.now.t)) + { + Grant(); + } + } + } + + private static int requirement = 10; + + private static float window = 10f; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MageBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMultiKillAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMultiKillAchievement.cs new file mode 100644 index 0000000..162560f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Mage/MageMultiKillAchievement.cs @@ -0,0 +1,61 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Mage; + +[RegisterAchievement("MageMultiKill", "Skills.Mage.LightningBolt", "FreeMage", 3u, typeof(MageMultiKillServerAchievement))] +public class MageMultiKillAchievement : BaseAchievement +{ + private class MageMultiKillServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + RoR2Application.onFixedUpdate += OnFixedUpdate; + } + + public override void OnUninstall() + { + RoR2Application.onFixedUpdate -= OnFixedUpdate; + base.OnUninstall(); + } + + private void OnFixedUpdate() + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody && requirement <= currentBody.multiKillCount) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + + private static readonly int requirement = 20; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MageBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "MageMultiKill"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..0c0dd43 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Merc; + +[RegisterAchievement("MercClearGameMonsoon", "Skins.Merc.Alt1", "CompleteUnknownEnding", 10u, null)] +public class MercClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MercBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercCompleteTrialWithFullHealthAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercCompleteTrialWithFullHealthAchievement.cs new file mode 100644 index 0000000..96e2102 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercCompleteTrialWithFullHealthAchievement.cs @@ -0,0 +1,131 @@ +namespace RoR2.Achievements.Merc; + +[RegisterAchievement("MercCompleteTrialWithFullHealth", "Skills.Merc.EvisProjectile", "CompleteUnknownEnding", 3u, typeof(MercCompleteTrialWithFullHealthServerAchievement))] +public class MercCompleteTrialWithFullHealthAchievement : BaseAchievement +{ + private class MercCompleteTrialWithFullHealthServerAchievement : BaseServerAchievement + { + private ToggleAction listenForDamage; + + private ToggleAction listenForGameOver; + + private bool failed; + + private bool runOk; + + public override void OnInstall() + { + base.OnInstall(); + listenForDamage = new ToggleAction(delegate + { + RoR2Application.onFixedUpdate += OnFixedUpdate; + }, delegate + { + RoR2Application.onFixedUpdate -= OnFixedUpdate; + }); + listenForGameOver = new ToggleAction(delegate + { + Run.onServerGameOver += OnServerGameOver; + }, delegate + { + Run.onServerGameOver -= OnServerGameOver; + }); + Run.onRunStartGlobal += OnRunStart; + Run.onRunDestroyGlobal += OnRunDestroy; + if ((bool)Run.instance) + { + OnRunDiscovered(Run.instance); + } + } + + public override void OnUninstall() + { + Run.onRunDestroyGlobal -= OnRunDestroy; + Run.onRunStartGlobal -= OnRunStart; + listenForGameOver.SetActive(newActive: false); + listenForDamage.SetActive(newActive: false); + base.OnUninstall(); + } + + private bool CharacterIsAtFullHealthOrNull() + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody) + { + return currentBody.healthComponent.fullCombinedHealth <= currentBody.healthComponent.combinedHealth; + } + return true; + } + + private void OnFixedUpdate() + { + if (!CharacterIsAtFullHealthOrNull()) + { + Fail(); + } + } + + private void Fail() + { + failed = true; + listenForDamage.SetActive(newActive: false); + listenForGameOver.SetActive(newActive: false); + } + + private void OnServerGameOver(Run run, GameEndingDef gameEndingDef) + { + if (gameEndingDef.isWin) + { + if (runOk && !failed) + { + Grant(); + } + runOk = false; + } + } + + private void OnRunStart(Run run) + { + OnRunDiscovered(run); + } + + private void OnRunDiscovered(Run run) + { + runOk = run is WeeklyRun; + if (runOk) + { + listenForGameOver.SetActive(newActive: true); + listenForDamage.SetActive(newActive: true); + failed = false; + } + } + + private void OnRunDestroy(Run run) + { + OnRunLost(run); + } + + private void OnRunLost(Run run) + { + listenForGameOver.SetActive(newActive: false); + listenForDamage.SetActive(newActive: false); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MercBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercDontTouchGroundAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercDontTouchGroundAchievement.cs new file mode 100644 index 0000000..db99c4b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercDontTouchGroundAchievement.cs @@ -0,0 +1,63 @@ +using Assets.RoR2.Scripts.Platform; +using UnityEngine; + +namespace RoR2.Achievements.Merc; + +[RegisterAchievement("MercDontTouchGround", "Skills.Merc.Uppercut", "CompleteUnknownEnding", 3u, null)] +public class MercDontTouchGroundAchievement : BaseAchievement +{ + private static readonly float requirement = 30f; + + private CharacterMotor motor; + + private CharacterBody body; + + private float stopwatch; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MercBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + RoR2Application.onFixedUpdate += MercFixedUpdate; + base.localUser.onBodyChanged += OnBodyChanged; + OnBodyChanged(); + } + + protected override void OnBodyRequirementBroken() + { + base.localUser.onBodyChanged -= OnBodyChanged; + RoR2Application.onFixedUpdate -= MercFixedUpdate; + base.OnBodyRequirementBroken(); + } + + private void OnBodyChanged() + { + body = base.localUser.cachedBody; + motor = (body ? body.characterMotor : null); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "MercDontTouchGround"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } + + private void MercFixedUpdate() + { + bool flag = (bool)motor && !motor.isGrounded && !body.currentVehicle; + stopwatch = (flag ? (stopwatch + Time.fixedDeltaTime) : 0f); + if (requirement <= stopwatch) + { + Grant(); + TryToCompleteActivity(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..b785805 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Merc; + +[RegisterAchievement("MercClearMeridianEvent", "Skins.Merc.Alt2", "CompleteUnknownEnding", 5u, typeof(MercMeridianEventTriggerServerAchievement))] +public class MercMeridianEventTriggerAchievement : BaseAchievement +{ + private class MercMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MercBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercXSkillsInYSecondsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercXSkillsInYSecondsAchievement.cs new file mode 100644 index 0000000..90d631c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Merc/MercXSkillsInYSecondsAchievement.cs @@ -0,0 +1,102 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Merc; + +[RegisterAchievement("MercXSkillsInYSeconds", "Skills.Merc.FocusedAssault", "CompleteUnknownEnding", 3u, null)] +public class MercXSkillsInYSecondsAchievement : BaseAchievement +{ + private static readonly int requiredSkillCount = 20; + + private static readonly float windowSecconds = 10f; + + private DoXInYSecondsTracker tracker; + + private CharacterBody _trackedBody; + + private CharacterBody trackedBody + { + get + { + return _trackedBody; + } + set + { + if ((object)_trackedBody != value) + { + if ((object)_trackedBody != null) + { + _trackedBody.onSkillActivatedAuthority -= OnSkillActivated; + } + _trackedBody = value; + if ((object)_trackedBody != null) + { + _trackedBody.onSkillActivatedAuthority += OnSkillActivated; + } + } + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("MercBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + trackedBody = base.localUser.cachedBody; + base.localUser.onBodyChanged += OnBodyChanged; + tracker.Clear(); + } + + protected override void OnBodyRequirementBroken() + { + if (base.localUser != null) + { + base.localUser.onBodyChanged -= OnBodyChanged; + } + trackedBody = null; + base.OnBodyRequirementBroken(); + if (tracker != null) + { + tracker.Clear(); + } + } + + private void OnBodyChanged() + { + trackedBody = base.localUser.cachedBody; + tracker.Clear(); + } + + public override void OnInstall() + { + base.OnInstall(); + tracker = new DoXInYSecondsTracker(requiredSkillCount, windowSecconds); + } + + public override void OnUninstall() + { + tracker = null; + base.OnUninstall(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "MercXSkillsInYSeconds"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } + + private void OnSkillActivated(GenericSkill skill) + { + if (tracker.Push(Run.FixedTimeStamp.now.t)) + { + Grant(); + TryToCompleteActivity(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerAirborneMultiKillAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerAirborneMultiKillAchievement.cs new file mode 100644 index 0000000..638cc81 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerAirborneMultiKillAchievement.cs @@ -0,0 +1,83 @@ +using Assets.RoR2.Scripts.Platform; +using EntityStates.Railgunner.Weapon; + +namespace RoR2.Achievements.Railgunner; + +[RegisterAchievement("RailgunnerAirborneMultiKill", "Skills.Railgunner.SpecialAlt1", null, 3u, typeof(RailgunnerAirborneMultiKillServerAchievement))] +public class RailgunnerAirborneMultiKillAchievement : BaseAchievement +{ + private class RailgunnerAirborneMultiKillServerAchievement : BaseServerAchievement + { + private int killCount; + + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + BaseFireSnipe.onFireSnipe += OnFireSnipe; + } + + private void OnFireSnipe(BaseFireSnipe state) + { + killCount = 0; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private bool CharacterIsInAir() + { + CharacterBody currentBody = base.networkUser.GetCurrentBody(); + if ((bool)currentBody && (bool)currentBody.characterMotor) + { + return !currentBody.characterMotor.isGrounded; + } + return false; + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if (damageReport.damageInfo.attacker == damageReport.damageInfo.inflictor && (object)damageReport.attackerMaster != null && (object)damageReport.attackerMaster == base.networkUser.master && CharacterIsInAir()) + { + killCount++; + if (requirement <= killCount) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + } + + private static readonly int requirement = 3; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("RailgunnerBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "RailgunnerAirborneMultiKill"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..574f290 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Railgunner; + +[RegisterAchievement("RailgunnerClearGameMonsoon", "Skins.RailGunner.Alt1", null, 10u, null)] +public class RailgunnerClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("RailgunnerBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerConsecutiveWeakPointsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerConsecutiveWeakPointsAchievement.cs new file mode 100644 index 0000000..d2f7ba5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerConsecutiveWeakPointsAchievement.cs @@ -0,0 +1,55 @@ +using Assets.RoR2.Scripts.Platform; +using EntityStates.Railgunner.Weapon; + +namespace RoR2.Achievements.Railgunner; + +[RegisterAchievement("RailgunnerConsecutiveWeakPoints", "Skills.Railgunner.SecondaryAlt1", null, 3u, null)] +public class RailgunnerConsecutiveWeakPointsAchievement : BaseAchievement +{ + private const int requirement = 30; + + private int consecutiveCount; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("RailgunnerBody"); + } + + protected override void OnBodyRequirementMet() + { + BaseFireSnipe.onWeakPointHit += OnWeakPointHit; + BaseFireSnipe.onWeakPointMissed += OnWeakPointMissed; + } + + protected override void OnBodyRequirementBroken() + { + BaseFireSnipe.onWeakPointHit -= OnWeakPointHit; + BaseFireSnipe.onWeakPointMissed -= OnWeakPointMissed; + consecutiveCount = 0; + } + + private void OnWeakPointMissed() + { + consecutiveCount = 0; + } + + private void OnWeakPointHit(DamageInfo damageInfo) + { + consecutiveCount++; + if (consecutiveCount >= 30) + { + Grant(); + TryToCompleteActivity(); + } + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "RailgunnerConsecutiveWeakPoints"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerDealMassiveDamageAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerDealMassiveDamageAchievement.cs new file mode 100644 index 0000000..049628b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerDealMassiveDamageAchievement.cs @@ -0,0 +1,43 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Railgunner; + +[RegisterAchievement("RailgunnerDealMassiveDamage", "Skills.Railgunner.UtilityAlt1", null, 3u, null)] +public class RailgunnerDealMassiveDamageAchievement : BaseAchievement +{ + private const float minimumDamage = 1000000f; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("RailgunnerBody"); + } + + protected override void OnBodyRequirementMet() + { + GlobalEventManager.onClientDamageNotified += onClientDamageNotified; + } + + protected override void OnBodyRequirementBroken() + { + GlobalEventManager.onClientDamageNotified -= onClientDamageNotified; + } + + private void onClientDamageNotified(DamageDealtMessage message) + { + if ((object)message.attacker == base.localUser.cachedBodyObject && message.damage >= 1000000f) + { + Grant(); + TryToCompleteActivity(); + } + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "RailgunnerDealMassiveDamage"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..c647a79 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Railgunner/RailgunnerMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Railgunner; + +[RegisterAchievement("RailgunnerClearMeridianEvent", "Skins.RailGunner.Alt2", null, 5u, typeof(RailgunnerMeridianEventTriggerServerAchievement))] +public class RailgunnerMeridianEventTriggerAchievement : BaseAchievement +{ + private class RailgunnerMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("RailgunnerBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Seeker/SeekerAirMultiHit.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Seeker/SeekerAirMultiHit.cs new file mode 100644 index 0000000..7a6b460 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Seeker/SeekerAirMultiHit.cs @@ -0,0 +1,98 @@ +using EntityStates.Seeker; +using UnityEngine; + +namespace RoR2.Achievements.Seeker; + +[RegisterAchievement("SeekerAirMultiHit", "Skills.Seeker.SoulSearch", null, 3u, typeof(SeekerAirMultiHitServerAchievement))] +public class SeekerAirMultiHit : BaseAchievement +{ + private class SeekerAirMultiHitServerAchievement : BaseServerAchievement + { + private int hitCount; + + private bool hasShotSpiritOrb; + + public override void OnInstall() + { + base.OnInstall(); + SpiritPunch.onSpiritOrbFired += OnSpiritPunch; + BlastAttack.BlastAttackMultiHit += MultiAirborneBlastAttack; + } + + public override void OnUninstall() + { + BlastAttack.BlastAttackMultiHit -= MultiAirborneBlastAttack; + SpiritPunch.onSpiritOrbFired -= OnSpiritPunch; + base.OnUninstall(); + } + + private void MultiAirborneBlastAttack(BlastAttack.HitPoint[] hitPoints, GameObject attacker) + { + hitCount = 0; + if (!(attacker != null)) + { + return; + } + CharacterMaster master = attacker.GetComponent().master; + if ((object)master == null || (object)master != base.networkUser.master || !hasShotSpiritOrb) + { + return; + } + for (int i = 0; i < hitPoints.Length; i++) + { + BlastAttack.HitPoint hitPoint = hitPoints[i]; + HealthComponent healthComponent = (hitPoint.hurtBox ? hitPoint.hurtBox.healthComponent : null); + if ((bool)healthComponent) + { + CharacterBody body = healthComponent.body; + if (VictimInAir(body)) + { + hitCount++; + } + } + } + if (hitCount >= requirement) + { + Grant(); + } + else + { + hasShotSpiritOrb = false; + } + } + + private bool VictimInAir(CharacterBody victimBody) + { + bool flag = false; + if (victimBody.baseNameToken == "WISP_BODY_NAME" || victimBody.baseNameToken == "GREATERWISP_BODY_NAME") + { + flag = true; + } + return ((bool)victimBody && (bool)victimBody.characterMotor && !victimBody.characterMotor.isGrounded) || flag; + } + + private void OnSpiritPunch(bool spiritOrbFired) + { + hasShotSpiritOrb = spiritOrbFired; + } + } + + private static readonly int requirement = 3; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("SeekerBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Seeker/SeekerClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Seeker/SeekerClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..6cef9a0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Seeker/SeekerClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Seeker; + +[RegisterAchievement("SeekerClearGameMonsoon", "Skins.Seeker.Alt1", null, 10u, null)] +public class SeekerClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("SeekerBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotBeatArenaLaterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotBeatArenaLaterAchievement.cs new file mode 100644 index 0000000..511a378 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotBeatArenaLaterAchievement.cs @@ -0,0 +1,52 @@ +using RoR2.Stats; + +namespace RoR2.Achievements.Toolbot; + +[RegisterAchievement("ToolbotBeatArenaLater", "Skills.Toolbot.SpecialAlt", "RepeatFirstTeleporter", 3u, typeof(ToolbotBeatArenaLaterServerAchievement))] +public class ToolbotBeatArenaLaterAchievement : BaseAchievement +{ + private class ToolbotBeatArenaLaterServerAchievement : BaseServerAchievement + { + private MemoizedGetComponent playerStatsComponentGetter; + + public override void OnInstall() + { + base.OnInstall(); + ArenaMissionController.onBeatArena += OnBeatArena; + } + + public override void OnUninstall() + { + ArenaMissionController.onBeatArena -= OnBeatArena; + base.OnInstall(); + } + + private void OnBeatArena() + { + PlayerStatsComponent playerStatsComponent = playerStatsComponentGetter.Get(base.networkUser.masterObject); + if ((bool)playerStatsComponent && playerStatsComponent.currentStats.GetStatValueULong(StatDef.highestStagesCompleted) >= 6) + { + Grant(); + } + } + } + + private const int requirement = 6; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ToolbotBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..4575a23 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Toolbot; + +[RegisterAchievement("ToolbotClearGameMonsoon", "Skins.Toolbot.Alt1", "RepeatFirstTeleporter", 10u, null)] +public class ToolbotClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ToolbotBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotGuardTeleporterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotGuardTeleporterAchievement.cs new file mode 100644 index 0000000..efcb8b0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotGuardTeleporterAchievement.cs @@ -0,0 +1,115 @@ +namespace RoR2.Achievements.Toolbot; + +[RegisterAchievement("ToolbotGuardTeleporter", "Skills.Toolbot.Grenade", "RepeatFirstTeleporter", 3u, typeof(ToolbotGuardTeleporterServerAchievement))] +public class ToolbotGuardTeleporterAchievement : BaseAchievement +{ + public class ToolbotGuardTeleporterServerAchievement : BaseServerAchievement + { + private bool stayedInZone; + + private int killCount; + + private int killRequirement = 2; + + private BodyIndex beetleQueenBodyIndex = BodyIndex.None; + + private Run.FixedTimeStamp teleporterStartChargingTime = Run.FixedTimeStamp.negativeInfinity; + + private static readonly float gracePeriod = 2f; + + public override void OnInstall() + { + base.OnInstall(); + TeleporterInteraction.onTeleporterBeginChargingGlobal += OnTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged; + killCount = 0; + beetleQueenBodyIndex = BodyCatalog.FindBodyIndex("BeetleQueen2Body"); + } + + public override void OnUninstall() + { + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged; + TeleporterInteraction.onTeleporterBeginChargingGlobal -= OnTeleporterBeginCharging; + SetStayedInZone(newStayedInZone: false); + base.OnUninstall(); + } + + private void OnTeleporterBeginCharging(TeleporterInteraction teleporterInteraction) + { + teleporterStartChargingTime = Run.FixedTimeStamp.now; + SetStayedInZone(newStayedInZone: true); + } + + private void OnTeleporterCharged(TeleporterInteraction teleporterInteraction) + { + SetStayedInZone(newStayedInZone: false); + } + + private void SetStayedInZone(bool newStayedInZone) + { + if (stayedInZone != newStayedInZone) + { + stayedInZone = newStayedInZone; + if (stayedInZone) + { + RoR2Application.onFixedUpdate += FixedUpdateTeleporterCharging; + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + UpdateStayedInZone(); + } + else + { + killCount = 0; + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + RoR2Application.onFixedUpdate -= FixedUpdateTeleporterCharging; + } + } + } + + private void FixedUpdateTeleporterCharging() + { + UpdateStayedInZone(); + } + + private void UpdateStayedInZone() + { + if (stayedInZone) + { + TeleporterInteraction instance = TeleporterInteraction.instance; + CharacterBody currentBody = GetCurrentBody(); + if ((!instance || !instance.holdoutZoneController.IsBodyInChargingRadius(currentBody)) && (teleporterStartChargingTime + gracePeriod).hasPassed) + { + SetStayedInZone(newStayedInZone: false); + } + } + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if (damageReport.victimBodyIndex == beetleQueenBodyIndex) + { + killCount++; + if (killCount >= killRequirement) + { + Grant(); + } + } + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ToolbotBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotKillImpBossWithBfgAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotKillImpBossWithBfgAchievement.cs new file mode 100644 index 0000000..b8bd4a2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotKillImpBossWithBfgAchievement.cs @@ -0,0 +1,51 @@ +namespace RoR2.Achievements.Toolbot; + +[RegisterAchievement("ToolbotKillImpBossWithBfg", "Skills.Toolbot.Buzzsaw", "RepeatFirstTeleporter", 3u, typeof(ToolbotKillImpBossWithBfgServerAchievement))] +public class ToolbotKillImpBossWithBfgAchievement : BaseAchievement +{ + private class ToolbotKillImpBossWithBfgServerAchievement : BaseServerAchievement + { + private BodyIndex impBossBodyIndex = BodyIndex.None; + + private int bfgProjectileIndex = -1; + + public override void OnInstall() + { + base.OnInstall(); + impBossBodyIndex = BodyCatalog.FindBodyIndex("ImpBossBody"); + bfgProjectileIndex = ProjectileCatalog.FindProjectileIndex("BeamSphere"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if ((bool)damageReport.victimBody && damageReport.victimBody.bodyIndex == impBossBodyIndex && IsCurrentBody(damageReport.damageInfo.attacker) && ProjectileCatalog.GetProjectileIndex(damageReport.damageInfo.inflictor) == bfgProjectileIndex) + { + Grant(); + } + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ToolbotBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..bd9933f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Toolbot/ToolbotMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Toolbot; + +[RegisterAchievement("ToolbotClearMeridianEvent", "Skins.Toolbot.Alt2", "RepeatFirstTeleporter", 5u, typeof(ToolbotMeridianEventTriggerServerAchievement))] +public class ToolbotMeridianEventTriggerAchievement : BaseAchievement +{ + private class ToolbotMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("ToolbotBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotBigHealAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotBigHealAchievement.cs new file mode 100644 index 0000000..b879f0d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotBigHealAchievement.cs @@ -0,0 +1,74 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Treebot; + +[RegisterAchievement("TreebotBigHeal", "Skills.Treebot.SpecialAlt1", "RescueTreebot", 3u, typeof(TreebotBigHealServerAchievement))] +public class TreebotBigHealAchievement : BaseAchievement +{ + private class TreebotBigHealServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + HealthComponent.onCharacterHealServer += OnCharacterHealServer; + } + + public override void OnUninstall() + { + HealthComponent.onCharacterHealServer -= OnCharacterHealServer; + base.OnInstall(); + } + + private void OnCharacterHealServer(HealthComponent healthComponent, float amount, ProcChainMask procChainMask) + { + if (amount >= requirement) + { + HealthComponent component = GetCurrentBody().GetComponent(); + if ((object)healthComponent == component) + { + Grant(); + ServerTryToCompleteActivity(); + } + } + } + } + + private static readonly float requirement = 1000f; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("TreebotBody"); + } + + public override void OnInstall() + { + base.OnInstall(); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "TreebotBigHeal"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..a83b59b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.Treebot; + +[RegisterAchievement("TreebotClearGameMonsoon", "Skins.Treebot.Alt1", "RescueTreebot", 10u, null)] +public class TreebotClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("TreebotBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotDunkClayBossAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotDunkClayBossAchievement.cs new file mode 100644 index 0000000..f79d58b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotDunkClayBossAchievement.cs @@ -0,0 +1,51 @@ +namespace RoR2.Achievements.Treebot; + +[RegisterAchievement("TreebotDunkClayBoss", "Skills.Treebot.PlantSonicBoom", "RescueTreebot", 3u, typeof(TreebotDunkClayBossServerAchievement))] +public class TreebotDunkClayBossAchievement : BaseAchievement +{ + private class TreebotDunkClayBossServerAchievement : BaseServerAchievement + { + private BodyIndex clayBossBodyIndex; + + private SceneDef requiredSceneDef; + + public override void OnInstall() + { + base.OnInstall(); + clayBossBodyIndex = BodyCatalog.FindBodyIndex("ClayBossBody"); + requiredSceneDef = SceneCatalog.GetSceneDefFromSceneName("goolake"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if (damageReport.victimBodyIndex == clayBossBodyIndex && IsCurrentBody(damageReport.attackerBody) && (bool)damageReport.damageInfo.inflictor && (bool)damageReport.damageInfo.inflictor.GetComponent() && SceneCatalog.mostRecentSceneDef == requiredSceneDef) + { + Grant(); + } + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + base.OnUninstall(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("TreebotBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotLowHealthTeleporterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotLowHealthTeleporterAchievement.cs new file mode 100644 index 0000000..a891bd4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotLowHealthTeleporterAchievement.cs @@ -0,0 +1,96 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements.Treebot; + +[RegisterAchievement("TreebotLowHealthTeleporter", "Skills.Treebot.Barrage", "RescueTreebot", 3u, null)] +public class TreebotLowHealthTeleporterAchievement : BaseAchievement +{ + private static readonly float requirement = 0.5f; + + private ToggleAction healthMonitor; + + private HealthComponent targetHealthComponent; + + private bool failed = true; + + private HealthComponent healthComponent; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("TreebotBody"); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "TreebotLowHealthTeleporter"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } + + private void OnTeleporterBeginChargingGlobal(TeleporterInteraction teleporterInteraction) + { + failed = false; + healthMonitor.SetActive(newActive: true); + } + + private void OnTeleporterChargedGlobal(TeleporterInteraction teleporterInteraction) + { + if (!failed) + { + Grant(); + TryToCompleteActivity(); + } + } + + private void SubscribeHealthMonitor() + { + RoR2Application.onFixedUpdate += OnFixedUpdateMonitorHealth; + } + + private void UnsubscribeHealthMonitor() + { + RoR2Application.onFixedUpdate -= OnFixedUpdateMonitorHealth; + } + + private void OnFixedUpdateMonitorHealth() + { + if (!healthComponent || requirement < healthComponent.combinedHealthFraction) + { + failed = true; + healthMonitor.SetActive(newActive: false); + } + } + + public override void OnInstall() + { + base.OnInstall(); + healthMonitor = new ToggleAction(SubscribeHealthMonitor, UnsubscribeHealthMonitor); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + TeleporterInteraction.onTeleporterBeginChargingGlobal += OnTeleporterBeginChargingGlobal; + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterChargedGlobal; + base.localUser.onBodyChanged += OnBodyChanged; + OnBodyChanged(); + } + + private void OnBodyChanged() + { + healthComponent = base.localUser.cachedBody?.healthComponent; + } + + protected override void OnBodyRequirementBroken() + { + base.localUser.onBodyChanged -= OnBodyChanged; + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterChargedGlobal; + TeleporterInteraction.onTeleporterBeginChargingGlobal -= OnTeleporterBeginChargingGlobal; + healthMonitor.SetActive(newActive: false); + healthComponent = null; + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..253b17f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.Treebot/TreebotMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.Treebot; + +[RegisterAchievement("TreebotClearMeridianEvent", "Skins.Treebot.Alt2", "RescueTreebot", 5u, typeof(TreebotMeridianEventTriggerServerAchievement))] +public class TreebotMeridianEventTriggerAchievement : BaseAchievement +{ + private class TreebotMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("TreebotBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.VoidSurvivor/VoidSurvivorClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.VoidSurvivor/VoidSurvivorClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..6dd4910 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.VoidSurvivor/VoidSurvivorClearGameMonsoonAchievement.cs @@ -0,0 +1,10 @@ +namespace RoR2.Achievements.VoidSurvivor; + +[RegisterAchievement("VoidSurvivorClearGameMonsoon", "Skins.VoidSurvivor.Alt1", "CompleteVoidEnding", 10u, null)] +public class VoidSurvivorClearGameMonsoonAchievement : BasePerSurvivorClearGameMonsoonAchievement +{ + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("VoidSurvivorBody"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements.VoidSurvivor/VoidSurvivorMeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements.VoidSurvivor/VoidSurvivorMeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..e4d90f3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements.VoidSurvivor/VoidSurvivorMeridianEventTriggerAchievement.cs @@ -0,0 +1,44 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements.VoidSurvivor; + +[RegisterAchievement("VoidSurvivorClearMeridianEvent", "Skins.VoidSurvivor.Alt2", "CompleteVoidEnding", 3u, typeof(VoidSurvivorMeridianEventTriggerServerAchievement))] +public class VoidSurvivorMeridianEventTriggerAchievement : BaseAchievement +{ + private class VoidSurvivorMeridianEventTriggerServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + Grant(); + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("VoidSurvivorBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/AttackSpeedAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/AttackSpeedAchievement.cs new file mode 100644 index 0000000..3009e4a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/AttackSpeedAchievement.cs @@ -0,0 +1,27 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("AttackSpeed", "Items.AttackSpeedOnCrit", null, 2u, null)] +public class AttackSpeedAchievement : BaseAchievement +{ + private const float requirement = 3f; + + public override void OnInstall() + { + base.OnInstall(); + RoR2Application.onUpdate += CheckAttackSpeed; + } + + public override void OnUninstall() + { + RoR2Application.onUpdate -= CheckAttackSpeed; + base.OnUninstall(); + } + + public void CheckAttackSpeed() + { + if (base.localUser != null && (bool)base.localUser.cachedBody && base.localUser.cachedBody.attackSpeed >= 3f) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/AutomationActivation.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/AutomationActivation.cs new file mode 100644 index 0000000..79ed94e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/AutomationActivation.cs @@ -0,0 +1,32 @@ +using JetBrains.Annotations; +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("AutomationActivation", "Items.Squid", null, 2u, typeof(AutomationActivation))] +public class AutomationActivation : BaseAchievement +{ + private static readonly ulong requirement = 6uL; + + private static StatDef statDef => StatDef.totalTurretsPurchased; + + public override void OnInstall() + { + base.OnInstall(); + owner.onRunStatsUpdated += OnRunStatsUpdated; + } + + public override void OnUninstall() + { + owner.onRunStatsUpdated -= OnRunStatsUpdated; + base.OnUninstall(); + } + + private void OnRunStatsUpdated([NotNull] StatSheet runStatSheet) + { + if (runStatSheet.GetStatValueULong(statDef) >= requirement) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseAchievement.cs new file mode 100644 index 0000000..e569b3d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseAchievement.cs @@ -0,0 +1,199 @@ +using Assets.RoR2.Scripts.Platform; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; + +namespace RoR2.Achievements; + +public abstract class BaseAchievement +{ + public UserAchievementManager owner; + + public bool shouldGrant; + + public bool shouldUpdateProgress; + + public AchievementDef achievementDef; + + private bool _meetsBodyRequirement; + + protected LocalUser localUser { get; private set; } + + protected UserProfile userProfile { get; private set; } + + protected bool isUserAlive + { + get + { + if (localUser != null && (bool)localUser.cachedBody && (bool)localUser.cachedBody.healthComponent) + { + return localUser.cachedBody.healthComponent.alive; + } + return false; + } + } + + protected BodyIndex requiredBodyIndex { get; private set; } = BodyIndex.None; + + + protected bool meetsBodyRequirement + { + get + { + return _meetsBodyRequirement; + } + set + { + if (_meetsBodyRequirement != value) + { + _meetsBodyRequirement = value; + if (_meetsBodyRequirement) + { + OnBodyRequirementMet(); + } + else + { + OnBodyRequirementBroken(); + } + } + } + } + + protected virtual bool wantsBodyCallbacks { get; } + + public virtual void OnInstall() + { + localUser = owner.localUser; + userProfile = owner.userProfile; + requiredBodyIndex = LookUpRequiredBodyIndex(); + if (requiredBodyIndex != BodyIndex.None) + { + localUser.onBodyChanged += HandleBodyChangedForBodyRequirement; + Run.onRunDestroyGlobal += SetBodyRequirementBrokenOnRunEnd; + } + } + + public virtual bool IsProgressiveAchievement() + { + return false; + } + + public virtual float ProgressForAchievement() + { + return 0f; + } + + public virtual ulong GetCurrentProgress() + { + return 0uL; + } + + public virtual ulong GetProgressRequirement() + { + return 100uL; + } + + public virtual void OnUninstall() + { + if (achievementDef.serverTrackerType != null) + { + SetServerTracked(shouldTrack: false); + } + if (requiredBodyIndex != BodyIndex.None) + { + Run.onRunDestroyGlobal -= SetBodyRequirementBrokenOnRunEnd; + localUser.onBodyChanged -= HandleBodyChangedForBodyRequirement; + meetsBodyRequirement = false; + } + owner = null; + localUser = null; + userProfile = null; + } + + public void Grant() + { + if (shouldGrant) + { + return; + } + UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(achievementDef.unlockableRewardIdentifier); + if ((bool)unlockableDef) + { + ExpansionDef expansionDefForUnlockable = UnlockableCatalog.GetExpansionDefForUnlockable(unlockableDef.index); + if ((bool)expansionDefForUnlockable && (bool)expansionDefForUnlockable.requiredEntitlement && !EntitlementManager.localUserEntitlementTracker.AnyUserHasEntitlement(expansionDefForUnlockable.requiredEntitlement)) + { + return; + } + } + if (!localUser.currentNetworkUser || localUser.currentNetworkUser.isParticipating) + { + shouldGrant = true; + owner.dirtyGrantsCount++; + } + } + + public virtual void OnGranted() + { + if (!string.IsNullOrEmpty(achievementDef.unlockableRewardIdentifier)) + { + if ((bool)localUser.currentNetworkUser) + { + UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(achievementDef.unlockableRewardIdentifier); + localUser.currentNetworkUser.CallCmdReportUnlock(unlockableDef.index); + } + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + string[] childAchievementIdentifiers = achievementDef.childAchievementIdentifiers; + foreach (string activityAchievementID in childAchievementIdentifiers) + { + baseActivitySelector.activityAchievementID = activityAchievementID; + PlatformSystems.activityManager.TryToSetActivityAvailability(baseActivitySelector, newAvailability: true); + } + userProfile.AddUnlockToken(achievementDef.unlockableRewardIdentifier); + } + if (achievementDef.lunarCoinReward != 0 && (bool)localUser.currentNetworkUser) + { + localUser.currentNetworkUser.CallCmdAwardLunarCoins(achievementDef.lunarCoinReward); + } + } + + public void UpdateProgress() + { + } + + public virtual void TryToCompleteActivity() + { + } + + public void SetServerTracked(bool shouldTrack) + { + owner.SetServerAchievementTracked(achievementDef.serverIndex, shouldTrack); + } + + protected virtual BodyIndex LookUpRequiredBodyIndex() + { + return BodyIndex.None; + } + + private void HandleBodyChangedForBodyRequirement() + { + bool num = localUser.cachedBody; + bool flag = meetsBodyRequirement; + if (num) + { + flag = localUser.cachedBody.bodyIndex == requiredBodyIndex; + } + meetsBodyRequirement = flag; + } + + protected virtual void OnBodyRequirementMet() + { + } + + protected virtual void OnBodyRequirementBroken() + { + } + + private void SetBodyRequirementBrokenOnRunEnd(Run run) + { + meetsBodyRequirement = false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseEndingAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseEndingAchievement.cs new file mode 100644 index 0000000..9ec4532 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseEndingAchievement.cs @@ -0,0 +1,27 @@ +namespace RoR2.Achievements; + +public abstract class BaseEndingAchievement : BaseAchievement +{ + protected abstract bool ShouldGrant(RunReport runReport); + + public override void OnInstall() + { + base.OnInstall(); + Run.onClientGameOverGlobal += OnClientGameOverGlobal; + } + + public override void OnUninstall() + { + Run.onClientGameOverGlobal -= OnClientGameOverGlobal; + base.OnUninstall(); + } + + protected virtual void OnClientGameOverGlobal(Run run, RunReport runReport) + { + if (ShouldGrant(runReport)) + { + Grant(); + } + TryToCompleteActivity(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BasePerSurvivorClearGameMonsoonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BasePerSurvivorClearGameMonsoonAchievement.cs new file mode 100644 index 0000000..95b1870 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BasePerSurvivorClearGameMonsoonAchievement.cs @@ -0,0 +1,28 @@ +namespace RoR2.Achievements; + +public class BasePerSurvivorClearGameMonsoonAchievement : BaseAchievement +{ + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + Run.onClientGameOverGlobal += OnClientGameOverGlobal; + } + + protected override void OnBodyRequirementBroken() + { + Run.onClientGameOverGlobal -= OnClientGameOverGlobal; + base.OnBodyRequirementBroken(); + } + + private void OnClientGameOverGlobal(Run run, RunReport runReport) + { + if ((bool)runReport.gameEnding && runReport.gameEnding.isWin) + { + DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(runReport.ruleBook.FindDifficulty()); + if (difficultyDef != null && difficultyDef.countsAsHardMode) + { + Grant(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseServerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseServerAchievement.cs new file mode 100644 index 0000000..63a5793 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseServerAchievement.cs @@ -0,0 +1,79 @@ +using System; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using UnityEngine; + +namespace RoR2.Achievements; + +public class BaseServerAchievement +{ + public ServerAchievementTracker serverAchievementTracker; + + public AchievementDef achievementDef; + + public NetworkUser networkUser => serverAchievementTracker.networkUser; + + protected CharacterBody GetCurrentBody() + { + return networkUser.GetCurrentBody(); + } + + protected bool IsCurrentBody(GameObject gameObject) + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody) + { + return (object)currentBody.gameObject == gameObject; + } + return false; + } + + protected bool IsCurrentBody(CharacterBody characterBody) + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody) + { + return (object)currentBody == characterBody; + } + return false; + } + + public virtual void OnInstall() + { + } + + public virtual void OnUninstall() + { + } + + protected void Grant() + { + UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(achievementDef.unlockableRewardIdentifier); + if ((bool)unlockableDef) + { + ExpansionDef expansionDefForUnlockable = UnlockableCatalog.GetExpansionDefForUnlockable(unlockableDef.index); + if ((bool)expansionDefForUnlockable && (bool)expansionDefForUnlockable.requiredEntitlement && !EntitlementManager.networkUserEntitlementTracker.UserHasEntitlement(networkUser, expansionDefForUnlockable.requiredEntitlement)) + { + return; + } + } + serverAchievementTracker.CallRpcGrantAchievement(achievementDef.serverIndex); + } + + protected void ServerTryToCompleteActivity() + { + serverAchievementTracker.CallRpcTryToCompleteActivity(achievementDef.serverIndex); + } + + public static BaseServerAchievement Instantiate(ServerAchievementIndex serverAchievementIndex) + { + AchievementDef achievementDef = AchievementManager.GetAchievementDef(serverAchievementIndex); + if (achievementDef == null || achievementDef.serverTrackerType == null) + { + return null; + } + BaseServerAchievement obj = (BaseServerAchievement)Activator.CreateInstance(achievementDef.serverTrackerType); + obj.achievementDef = achievementDef; + return obj; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseStatMilestoneAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseStatMilestoneAchievement.cs new file mode 100644 index 0000000..ad6af95 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BaseStatMilestoneAchievement.cs @@ -0,0 +1,62 @@ +using System; +using RoR2.Stats; + +namespace RoR2.Achievements; + +public abstract class BaseStatMilestoneAchievement : BaseAchievement +{ + protected abstract StatDef statDef { get; } + + protected abstract ulong statRequirement { get; } + + private ulong statProgress => base.userProfile.statSheet.GetStatValueULong(statDef); + + public override void OnInstall() + { + base.OnInstall(); + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(Check)); + if (IsProgressiveAchievement()) + { + StatDef obj2 = statDef; + obj2.onChangeCallback = (Action)Delegate.Combine(obj2.onChangeCallback, new Action(base.UpdateProgress)); + } + Check(); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(Check)); + if (IsProgressiveAchievement()) + { + StatDef obj2 = statDef; + obj2.onChangeCallback = (Action)Delegate.Remove(obj2.onChangeCallback, new Action(base.UpdateProgress)); + } + base.OnUninstall(); + } + + public override float ProgressForAchievement() + { + return (float)statProgress / (float)statRequirement; + } + + public override ulong GetCurrentProgress() + { + return statProgress; + } + + public override ulong GetProgressRequirement() + { + return statRequirement; + } + + private void Check() + { + if (statProgress >= statRequirement) + { + Grant(); + TryToCompleteActivity(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BeatArenaAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BeatArenaAchievement.cs new file mode 100644 index 0000000..b0e95bf --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BeatArenaAchievement.cs @@ -0,0 +1,36 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("BeatArena", "Characters.Croco", null, 3u, typeof(BeatArenaServerAchievement))] +public class BeatArenaAchievement : BaseAchievement +{ + private class BeatArenaServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + ArenaMissionController.onBeatArena += OnBeatArena; + } + + public override void OnUninstall() + { + ArenaMissionController.onBeatArena -= OnBeatArena; + base.OnInstall(); + } + + private void OnBeatArena() + { + Grant(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/BurnToDeathAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/BurnToDeathAchievement.cs new file mode 100644 index 0000000..6b7c28c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/BurnToDeathAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("BurnToDeath", "Items.Cleanse", null, 2u, null)] +public class BurnToDeathAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalDeathsWhileBurning; + + protected override ulong statRequirement => 3uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CaptainBuyMegaDroneAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CaptainBuyMegaDroneAchievement.cs new file mode 100644 index 0000000..f4d43fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CaptainBuyMegaDroneAchievement.cs @@ -0,0 +1,51 @@ +using UnityEngine; + +namespace RoR2.Achievements; + +[RegisterAchievement("CaptainBuyMegaDrone", "Skills.Captain.CaptainSupplyDropHacking", "CompleteMainEnding", 3u, typeof(CaptainBuyMegaDroneServerAchievement))] +public class CaptainBuyMegaDroneAchievement : BaseAchievement +{ + private class CaptainBuyMegaDroneServerAchievement : BaseServerAchievement + { + private GameObject megaDroneMasterPrefab; + + public override void OnInstall() + { + base.OnInstall(); + megaDroneMasterPrefab = MasterCatalog.FindMasterPrefab("MegaDroneMaster"); + GlobalEventManager.OnInteractionsGlobal += OnInteractionsGlobal; + } + + public override void OnUninstall() + { + GlobalEventManager.OnInteractionsGlobal -= OnInteractionsGlobal; + megaDroneMasterPrefab = null; + base.OnUninstall(); + } + + private void OnInteractionsGlobal(Interactor interactor, IInteractable interactable, GameObject interactableObject) + { + if (IsCurrentBody(interactor.gameObject) && interactableObject.GetComponent()?.masterPrefab == megaDroneMasterPrefab) + { + Grant(); + } + } + } + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CaptainBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CaptainVisitSeveralStagesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CaptainVisitSeveralStagesAchievement.cs new file mode 100644 index 0000000..28dd5f6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CaptainVisitSeveralStagesAchievement.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using Assets.RoR2.Scripts.Platform; +using HG; + +namespace RoR2.Achievements; + +[RegisterAchievement("CaptainVisitSeveralStages", "Skills.Captain.CaptainSupplyDropEquipmentRestock", "CompleteMainEnding", 3u, null)] +public class CaptainVisitSeveralStagesAchievement : BaseAchievement +{ + private static readonly int requirement = 10; + + private List visitedScenes; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("CaptainBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + visitedScenes = CollectionPool>.RentCollection(); + SceneCatalog.onMostRecentSceneDefChanged += HandleMostRecentSceneDefChanged; + } + + protected override void OnBodyRequirementBroken() + { + SceneCatalog.onMostRecentSceneDefChanged -= HandleMostRecentSceneDefChanged; + visitedScenes = CollectionPool>.ReturnCollection(visitedScenes); + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "CaptainVisitSeveralStages"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } + + private void HandleMostRecentSceneDefChanged(SceneDef newSceneDef) + { + if (!visitedScenes.Contains(newSceneDef)) + { + visitedScenes.Add(newSceneDef); + } + if (visitedScenes.Count >= requirement) + { + Grant(); + TryToCompleteActivity(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CarryLunarItemsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CarryLunarItemsAchievement.cs new file mode 100644 index 0000000..c1ef1fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CarryLunarItemsAchievement.cs @@ -0,0 +1,69 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CarryLunarItems", "Items.Meteor", null, 2u, null)] +public class CarryLunarItemsAchievement : BaseAchievement +{ + public const int requirement = 5; + + private PlayerCharacterMasterController currentMasterController; + + private Inventory currentInventory; + + public override void OnInstall() + { + base.OnInstall(); + base.localUser.onMasterChanged += OnMasterChanged; + SetMasterController(base.localUser.cachedMasterController); + } + + public override void OnUninstall() + { + SetMasterController(null); + base.localUser.onMasterChanged -= OnMasterChanged; + base.OnUninstall(); + } + + private void SetMasterController(PlayerCharacterMasterController newMasterController) + { + if ((object)currentMasterController != newMasterController) + { + if ((object)currentInventory != null) + { + currentInventory.onInventoryChanged -= OnInventoryChanged; + } + currentMasterController = newMasterController; + currentInventory = currentMasterController?.master?.inventory; + if ((object)currentInventory != null) + { + currentInventory.onInventoryChanged += OnInventoryChanged; + } + } + } + + private void OnInventoryChanged() + { + if ((bool)currentInventory) + { + int num = 5; + EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(currentInventory.currentEquipmentIndex); + if (equipmentDef != null && equipmentDef.isLunar) + { + num--; + } + EquipmentDef equipmentDef2 = EquipmentCatalog.GetEquipmentDef(currentInventory.alternateEquipmentIndex); + if (equipmentDef2 != null && equipmentDef2.isLunar) + { + num--; + } + if (currentInventory.HasAtLeastXTotalItemsOfTier(ItemTier.Lunar, num)) + { + Grant(); + } + } + } + + private void OnMasterChanged() + { + SetMasterController(base.localUser.cachedMasterController); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/ChargeTeleporterWhileNearDeathAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/ChargeTeleporterWhileNearDeathAchievement.cs new file mode 100644 index 0000000..f4da817 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/ChargeTeleporterWhileNearDeathAchievement.cs @@ -0,0 +1,32 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("ChargeTeleporterWhileNearDeath", "Items.WarCryOnMultiKill", null, 2u, null)] +public class ChargeTeleporterWhileNearDeathAchievement : BaseAchievement +{ + private const float requirement = 0.1f; + + public override void OnInstall() + { + base.OnInstall(); + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged; + } + + public override void OnUninstall() + { + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged; + base.OnUninstall(); + } + + private void OnTeleporterCharged(TeleporterInteraction teleporterInteraction) + { + Check(); + } + + private void Check() + { + if ((bool)base.localUser.cachedBody && (bool)base.localUser.cachedBody.healthComponent && base.localUser.cachedBody.healthComponent.alive && base.localUser.cachedBody.healthComponent.combinedHealthFraction <= 0.1f) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CleanupDuty.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CleanupDuty.cs new file mode 100644 index 0000000..cad4573 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CleanupDuty.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("CleanupDuty", "Items.Recycle", null, 2u, null)] +public class CleanupDuty : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalMaulingRockKills; + + protected override ulong statRequirement => 20uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/Complete20StagesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/Complete20StagesAchievement.cs new file mode 100644 index 0000000..251fb26 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/Complete20StagesAchievement.cs @@ -0,0 +1,63 @@ +using System; +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("Complete20Stages", "Items.Clover", null, 3u, null)] +public class Complete20StagesAchievement : BaseAchievement +{ + private const int requirement = 20; + + private bool listeningForStats; + + private UserProfile subscribedProfile; + + private MemoizedGetComponent playerStatsComponentGetter; + + public override void OnInstall() + { + base.OnInstall(); + Run.onRunStartGlobal += OnRunStart; + } + + public override void OnUninstall() + { + Run.onRunStartGlobal -= OnRunStart; + SetListeningForStats(shouldListen: false); + base.OnUninstall(); + } + + private void OnRunStart(Run run) + { + SetListeningForStats(shouldListen: true); + } + + private void SetListeningForStats(bool shouldListen) + { + if (listeningForStats != shouldListen) + { + listeningForStats = shouldListen; + if (listeningForStats) + { + subscribedProfile = base.localUser.userProfile; + UserProfile obj = subscribedProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(OnStatsReceived)); + } + else + { + UserProfile obj2 = subscribedProfile; + obj2.onStatsReceived = (Action)Delegate.Remove(obj2.onStatsReceived, new Action(OnStatsReceived)); + subscribedProfile = null; + } + } + } + + private void OnStatsReceived() + { + PlayerStatsComponent playerStatsComponent = playerStatsComponentGetter.Get(base.localUser.cachedMasterObject); + if ((bool)playerStatsComponent && playerStatsComponent.currentStats.GetStatValueULong(StatDef.highestStagesCompleted) >= 20) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/Complete30StagesCareerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/Complete30StagesCareerAchievement.cs new file mode 100644 index 0000000..28756ff --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/Complete30StagesCareerAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("Complete30StagesCareer", "Characters.Engineer", null, 3u, null)] +public class Complete30StagesCareerAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalStagesCompleted; + + protected override ulong statRequirement => 30uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMainEndingAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMainEndingAchievement.cs new file mode 100644 index 0000000..29d323c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMainEndingAchievement.cs @@ -0,0 +1,27 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteMainEnding", "Characters.Captain", null, 3u, null)] +public class CompleteMainEndingAchievement : BaseEndingAchievement +{ + protected override bool ShouldGrant(RunReport runReport) + { + if (runReport.gameEnding == RoR2Content.GameEndings.MainEnding) + { + return true; + } + return false; + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "CompleteMainEnding"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMainEndingHardAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMainEndingHardAchievement.cs new file mode 100644 index 0000000..c195aad --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMainEndingHardAchievement.cs @@ -0,0 +1,14 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteMainEndingHard", "Items.LunarBadLuck", null, 10u, null)] +public class CompleteMainEndingHardAchievement : BaseEndingAchievement +{ + protected override bool ShouldGrant(RunReport runReport) + { + if (runReport.gameEnding == RoR2Content.GameEndings.MainEnding && runReport.ruleBook.FindDifficulty() >= DifficultyIndex.Hard) + { + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMultiBossShrineAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMultiBossShrineAchievement.cs new file mode 100644 index 0000000..07654b5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteMultiBossShrineAchievement.cs @@ -0,0 +1,51 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteMultiBossShrine", "Items.Lightning", null, 2u, typeof(CompleteMultiBossShrineServerAchievement))] +public class CompleteMultiBossShrineAchievement : BaseAchievement +{ + private class CompleteMultiBossShrineServerAchievement : BaseServerAchievement + { + private const int requirement = 2; + + public override void OnInstall() + { + base.OnInstall(); + BossGroup.onBossGroupDefeatedServer += OnBossGroupDefeatedServer; + } + + public override void OnUninstall() + { + BossGroup.onBossGroupDefeatedServer -= OnBossGroupDefeatedServer; + base.OnUninstall(); + } + + private void OnBossGroupDefeatedServer(BossGroup bossGroup) + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody && (bool)currentBody.healthComponent && currentBody.healthComponent.alive && (bool)TeleporterInteraction.instance && CheckTeleporter(bossGroup, TeleporterInteraction.instance)) + { + Grant(); + } + } + + private bool CheckTeleporter(BossGroup bossGroup, TeleporterInteraction teleporterInteraction) + { + if (teleporterInteraction.bossDirector.combatSquad == bossGroup.combatSquad) + { + return teleporterInteraction.shrineBonusStacks >= 2; + } + return false; + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompletePrismaticTrialAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompletePrismaticTrialAchievement.cs new file mode 100644 index 0000000..0cca79b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompletePrismaticTrialAchievement.cs @@ -0,0 +1,23 @@ +using Assets.RoR2.Scripts.Platform; + +namespace RoR2.Achievements; + +[RegisterAchievement("CompletePrismaticTrial", "Items.HealOnCrit", null, 2u, null)] +public class CompletePrismaticTrialAchievement : BaseEndingAchievement +{ + protected override bool ShouldGrant(RunReport runReport) + { + return runReport.gameEnding == GameEndingCatalog.FindGameEndingDef("PrismaticTrialEnding"); + } + + public override void TryToCompleteActivity() + { + bool flag = base.localUser.id == LocalUserManager.GetFirstLocalUser().id; + if (shouldGrant && flag) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "CompletePrismaticTrial"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteTeleporterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteTeleporterAchievement.cs new file mode 100644 index 0000000..bad1a68 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteTeleporterAchievement.cs @@ -0,0 +1,56 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteTeleporter", "Items.BossDamageBonus", null, 1u, typeof(CompleteTeleporterServerAchievement))] +public class CompleteTeleporterAchievement : BaseAchievement +{ + private class CompleteTeleporterServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SceneExitController.onBeginExit += OnSceneBeginExit; + SceneExitControllerColossusPortal.onBeginExit += OnSceneColossusExit; + } + + public override void OnUninstall() + { + SceneExitController.onBeginExit -= OnSceneBeginExit; + SceneExitControllerColossusPortal.onBeginExit -= OnSceneColossusExit; + base.OnInstall(); + } + + private void OnSceneBeginExit(SceneExitController exitController) + { + if (exitController.portalUsedAfterTeleporterEventFinish) + { + Check(); + } + } + + private void OnSceneColossusExit(SceneExitControllerColossusPortal exitColossusController) + { + Check(); + } + + private void Check() + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody && (bool)currentBody.healthComponent && currentBody.healthComponent.alive) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + SetServerTracked(shouldTrack: false); + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteTeleporterWithoutInjuryAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteTeleporterWithoutInjuryAchievement.cs new file mode 100644 index 0000000..f6349e5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteTeleporterWithoutInjuryAchievement.cs @@ -0,0 +1,49 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteTeleporterWithoutInjury", "Items.SecondarySkillMagazine", null, 1u, null)] +public class CompleteTeleporterWithoutInjuryAchievement : BaseAchievement +{ + private bool hasBeenHit; + + public override void OnInstall() + { + base.OnInstall(); + TeleporterInteraction.onTeleporterBeginChargingGlobal += OnTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged; + GlobalEventManager.onClientDamageNotified += OnClientDamageNotified; + } + + public override void OnUninstall() + { + TeleporterInteraction.onTeleporterBeginChargingGlobal -= OnTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged; + GlobalEventManager.onClientDamageNotified -= OnClientDamageNotified; + base.OnUninstall(); + } + + private void OnTeleporterBeginCharging(TeleporterInteraction teleporterInteraction) + { + hasBeenHit = false; + } + + private void OnTeleporterCharged(TeleporterInteraction teleporterInteraction) + { + Check(); + } + + private void OnClientDamageNotified(DamageDealtMessage damageDealtMessage) + { + if (!hasBeenHit && (bool)damageDealtMessage.victim && damageDealtMessage.victim == base.localUser.cachedBodyObject) + { + hasBeenHit = true; + } + } + + private void Check() + { + if ((bool)base.localUser.cachedBody && (bool)base.localUser.cachedBody.healthComponent && base.localUser.cachedBody.healthComponent.alive && !hasBeenHit) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteThreeStagesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteThreeStagesAchievement.cs new file mode 100644 index 0000000..73f656e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteThreeStagesAchievement.cs @@ -0,0 +1,38 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteThreeStages", "Characters.Bandit2", null, 3u, null)] +public class CompleteThreeStagesAchievement : BaseAchievement +{ + private const int requirement = 3; + + public override void OnInstall() + { + base.OnInstall(); + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged; + } + + public override void OnUninstall() + { + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged; + base.OnUninstall(); + } + + private void OnTeleporterCharged(TeleporterInteraction teleporterInteraction) + { + Check(); + } + + private void Check() + { + if ((bool)Run.instance && Run.instance.GetType() == typeof(Run)) + { + SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); + if (!(sceneDefForCurrentScene == null) && base.localUser.currentNetworkUser.masterPlayerStatsComponent.currentStats.GetStatValueULong(StatDef.totalDeaths) == 0L && sceneDefForCurrentScene.stageOrder == 3) + { + Grant(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteThreeStagesWithoutHealingsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteThreeStagesWithoutHealingsAchievement.cs new file mode 100644 index 0000000..77ffde0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteThreeStagesWithoutHealingsAchievement.cs @@ -0,0 +1,59 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteThreeStagesWithoutHealing", "Items.IncreaseHealing", null, 3u, typeof(CompleteThreeStagesWithoutHealingServerAchievement))] +public class CompleteThreeStagesWithoutHealingsAchievement : BaseAchievement +{ + private class CompleteThreeStagesWithoutHealingServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SceneExitController.onBeginExit += OnSceneBeginExit; + } + + public override void OnUninstall() + { + SceneExitController.onBeginExit -= OnSceneBeginExit; + base.OnUninstall(); + } + + private void OnSceneBeginExit(SceneExitController exitController) + { + Check(); + } + + private void Check() + { + if (!Run.instance || !(Run.instance.GetType() == typeof(Run)) || !(serverAchievementTracker != null) || !(base.networkUser != null) || serverAchievementTracker == null || serverAchievementTracker.networkUser == null) + { + return; + } + SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); + if (!(base.networkUser.masterPlayerStatsComponent == null) && base.networkUser.masterPlayerStatsComponent.currentStats != null) + { + StatSheet currentStats = base.networkUser.masterPlayerStatsComponent.currentStats; + CharacterBody currentBody = GetCurrentBody(); + if (sceneDefForCurrentScene != null && currentStats.GetStatValueULong(StatDef.highestStagesCompleted) >= 2 && (float)currentStats.GetStatValueULong(StatDef.totalHealthHealed) <= 0f && (bool)currentBody && (bool)currentBody.healthComponent && currentBody.healthComponent.alive) + { + Grant(); + } + } + } + } + + private const int requirement = 2; + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + SetServerTracked(shouldTrack: false); + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteUnknownEndingAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteUnknownEndingAchievement.cs new file mode 100644 index 0000000..4f9168a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteUnknownEndingAchievement.cs @@ -0,0 +1,39 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteUnknownEnding", "Characters.Mercenary", null, 3u, typeof(CompleteUnknownEndingServerAchievement))] +public class CompleteUnknownEndingAchievement : BaseAchievement +{ + private class CompleteUnknownEndingServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + Run.onServerGameOver += OnServerGameOver; + } + + public override void OnUninstall() + { + base.OnInstall(); + Run.onServerGameOver -= OnServerGameOver; + } + + private void OnServerGameOver(Run run, GameEndingDef gameEndingDef) + { + if (gameEndingDef == RoR2Content.GameEndings.ObliterationEnding || gameEndingDef == RoR2Content.GameEndings.LimboEnding) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteVoidEndingAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteVoidEndingAchievement.cs new file mode 100644 index 0000000..39eb569 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/CompleteVoidEndingAchievement.cs @@ -0,0 +1,52 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("CompleteVoidEnding", "Characters.VoidSurvivor", null, 3u, typeof(CompleteWave50ServerAchievement))] +public class CompleteVoidEndingAchievement : BaseEndingAchievement +{ + private class CompleteWave50ServerAchievement : BaseServerAchievement + { + public const int waveRequirement = 50; + + public override void OnInstall() + { + base.OnInstall(); + InfiniteTowerRun.onAllEnemiesDefeatedServer += OnAllEnemiesDefeatedServer; + } + + public override void OnUninstall() + { + InfiniteTowerRun.onAllEnemiesDefeatedServer -= OnAllEnemiesDefeatedServer; + base.OnUninstall(); + } + + private void OnAllEnemiesDefeatedServer(InfiniteTowerWaveController waveController) + { + InfiniteTowerRun infiniteTowerRun = Run.instance as InfiniteTowerRun; + if ((bool)infiniteTowerRun && infiniteTowerRun.waveIndex >= 50) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + SetServerTracked(shouldTrack: false); + base.OnUninstall(); + } + + protected override bool ShouldGrant(RunReport runReport) + { + if (runReport.gameEnding == DLC1Content.GameEndings.VoidEnding) + { + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/DefeatFalseSonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/DefeatFalseSonAchievement.cs new file mode 100644 index 0000000..cf5df4d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/DefeatFalseSonAchievement.cs @@ -0,0 +1,38 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements; + +[RegisterAchievement("DefeatFalseSon", "Items.HealAndRevive", null, 5u, typeof(DefeatFalseSonServerAchievement))] +public class DefeatFalseSonAchievement : BaseAchievement +{ + private class DefeatFalseSonServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnFalseSonDefeated; + } + + public override void OnUninstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnFalseSonDefeated; + } + + private void OnFalseSonDefeated() + { + Grant(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/DefeatSuperRoboBallBossAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/DefeatSuperRoboBallBossAchievement.cs new file mode 100644 index 0000000..f029c3d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/DefeatSuperRoboBallBossAchievement.cs @@ -0,0 +1,42 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("DefeatSuperRoboBallBoss", "Characters.Loader", null, 3u, typeof(DefeatSuperRoboBallBossServerAchievement))] +public class DefeatSuperRoboBallBossAchievement : BaseAchievement +{ + private class DefeatSuperRoboBallBossServerAchievement : BaseServerAchievement + { + private BodyIndex superRoboBallBossBodyIndex; + + public override void OnInstall() + { + base.OnInstall(); + superRoboBallBossBodyIndex = BodyCatalog.FindBodyIndex("SuperRoboBallBossBody"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if (damageReport.victimBodyIndex == superRoboBallBossBodyIndex && damageReport.victimTeamIndex != TeamIndex.Player) + { + Grant(); + } + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + base.OnUninstall(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/Die20TimesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/Die20TimesAchievement.cs new file mode 100644 index 0000000..d158dc9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/Die20TimesAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("Die20Times", "Items.DeathProjectile", null, 2u, null)] +public class Die20TimesAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalDeaths; + + protected override ulong statRequirement => 20uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/Die5TimesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/Die5TimesAchievement.cs new file mode 100644 index 0000000..651eda9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/Die5TimesAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("Die5Times", "Items.Bear", null, 1u, null)] +public class Die5TimesAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalDeaths; + + protected override ulong statRequirement => 5uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/Discover10UniqueTier1Achievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/Discover10UniqueTier1Achievement.cs new file mode 100644 index 0000000..e384372 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/Discover10UniqueTier1Achievement.cs @@ -0,0 +1,60 @@ +using System; + +namespace RoR2.Achievements; + +[RegisterAchievement("Discover10UniqueTier1", "Items.Crowbar", null, 1u, null)] +public class Discover10UniqueTier1Achievement : BaseAchievement +{ + private const int requirement = 10; + + public override void OnInstall() + { + base.OnInstall(); + UserProfile obj = base.userProfile; + obj.onPickupDiscovered = (Action)Delegate.Combine(obj.onPickupDiscovered, new Action(OnPickupDiscovered)); + Check(); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onPickupDiscovered = (Action)Delegate.Remove(obj.onPickupDiscovered, new Action(OnPickupDiscovered)); + base.OnUninstall(); + } + + public override float ProgressForAchievement() + { + return (float)UniqueTier1Discovered() / 10f; + } + + private void OnPickupDiscovered(PickupIndex pickupIndex) + { + ItemIndex itemIndex = PickupCatalog.GetPickupDef(pickupIndex)?.itemIndex ?? ItemIndex.None; + if (itemIndex != ItemIndex.None && ItemCatalog.GetItemDef(itemIndex).tier == ItemTier.Tier1) + { + Check(); + } + } + + private int UniqueTier1Discovered() + { + int num = 0; + ItemIndex itemIndex = ItemIndex.Count; + for (ItemIndex itemCount = (ItemIndex)ItemCatalog.itemCount; itemIndex < itemCount; itemIndex++) + { + if (ItemCatalog.GetItemDef(itemIndex).tier == ItemTier.Tier1 && base.userProfile.HasDiscoveredPickup(PickupCatalog.FindPickupIndex(itemIndex))) + { + num++; + } + } + return num; + } + + private void Check() + { + if (UniqueTier1Discovered() >= 10) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/Discover5EquipmentAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/Discover5EquipmentAchievement.cs new file mode 100644 index 0000000..ef6f6e2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/Discover5EquipmentAchievement.cs @@ -0,0 +1,59 @@ +using System; + +namespace RoR2.Achievements; + +[RegisterAchievement("Discover5Equipment", "Items.EquipmentMagazine", null, 2u, null)] +public class Discover5EquipmentAchievement : BaseAchievement +{ + private const int requirement = 5; + + public override void OnInstall() + { + base.OnInstall(); + UserProfile obj = base.userProfile; + obj.onPickupDiscovered = (Action)Delegate.Combine(obj.onPickupDiscovered, new Action(OnPickupDiscovered)); + Check(); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onPickupDiscovered = (Action)Delegate.Remove(obj.onPickupDiscovered, new Action(OnPickupDiscovered)); + base.OnUninstall(); + } + + public override float ProgressForAchievement() + { + return (float)EquipmentDiscovered() / 5f; + } + + private void OnPickupDiscovered(PickupIndex pickupIndex) + { + if ((PickupCatalog.GetPickupDef(pickupIndex)?.equipmentIndex ?? EquipmentIndex.None) != EquipmentIndex.None) + { + Check(); + } + } + + private int EquipmentDiscovered() + { + int num = 0; + EquipmentIndex equipmentIndex = (EquipmentIndex)0; + for (EquipmentIndex equipmentCount = (EquipmentIndex)EquipmentCatalog.equipmentCount; equipmentIndex < equipmentCount; equipmentIndex++) + { + if (base.userProfile.HasDiscoveredPickup(PickupCatalog.FindPickupIndex(equipmentIndex))) + { + num++; + } + } + return num; + } + + private void Check() + { + if (EquipmentDiscovered() >= 5) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/FailShrineChanceAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/FailShrineChanceAchievement.cs new file mode 100644 index 0000000..4a35405 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/FailShrineChanceAchievement.cs @@ -0,0 +1,63 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("FailShrineChance", "Items.Hoof", null, 1u, typeof(FailShrineChanceServerAchievement))] +public class FailShrineChanceAchievement : BaseAchievement +{ + private class FailShrineChanceServerAchievement : BaseServerAchievement + { + private int failedInARow; + + private const int requirement = 3; + + public override void OnInstall() + { + base.OnInstall(); + ShrineChanceBehavior.onShrineChancePurchaseGlobal += OnShrineChancePurchase; + Run.onRunStartGlobal += OnRunStartGlobal; + } + + public override void OnUninstall() + { + base.OnInstall(); + ShrineChanceBehavior.onShrineChancePurchaseGlobal -= OnShrineChancePurchase; + Run.onRunStartGlobal -= OnRunStartGlobal; + } + + private void OnRunStartGlobal(Run run) + { + failedInARow = 0; + } + + private void OnShrineChancePurchase(bool failed, Interactor interactor) + { + CharacterBody currentBody = serverAchievementTracker.networkUser.GetCurrentBody(); + if (!currentBody || !(currentBody.GetComponent() == interactor)) + { + return; + } + if (failed) + { + failedInARow++; + if (failedInARow >= 3) + { + Grant(); + } + } + else + { + failedInARow = 0; + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/FindDevilAltarAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/FindDevilAltarAchievement.cs new file mode 100644 index 0000000..c321fd0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/FindDevilAltarAchievement.cs @@ -0,0 +1,24 @@ +using EntityStates.Destructible; + +namespace RoR2.Achievements; + +[RegisterAchievement("FindDevilAltar", "Items.NovaOnHeal", null, 3u, null)] +public class FindDevilAltarAchievement : BaseAchievement +{ + public override void OnInstall() + { + base.OnInstall(); + AltarSkeletonDeath.onDeath += OnDeath; + } + + public override void OnUninstall() + { + base.OnUninstall(); + AltarSkeletonDeath.onDeath -= OnDeath; + } + + private void OnDeath() + { + Grant(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/FindTimedChestAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/FindTimedChestAchievement.cs new file mode 100644 index 0000000..6d6bdd0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/FindTimedChestAchievement.cs @@ -0,0 +1,38 @@ +using EntityStates.TimedChest; + +namespace RoR2.Achievements; + +[RegisterAchievement("FindTimedChest", "Items.BFG", null, 2u, typeof(FindTimedChestServerAchievement))] +public class FindTimedChestAchievement : BaseAchievement +{ + private class FindTimedChestServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + Opening.onOpened += OnOpened; + } + + public override void OnUninstall() + { + base.OnInstall(); + Opening.onOpened -= OnOpened; + } + + private void OnOpened() + { + Grant(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/FindUniqueNewtStatues.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/FindUniqueNewtStatues.cs new file mode 100644 index 0000000..132a61c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/FindUniqueNewtStatues.cs @@ -0,0 +1,63 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("FindUniqueNewtStatues", "Items.Talisman", null, 3u, null)] +public class FindUniqueNewtStatues : BaseAchievement +{ + private const int requirement = 8; + + public override void OnInstall() + { + base.OnInstall(); + Check(); + UserProfile.onUnlockableGranted += OnUnlockCheck; + } + + public override void OnUninstall() + { + UserProfile.onUnlockableGranted -= OnUnlockCheck; + base.OnUninstall(); + } + + public override float ProgressForAchievement() + { + return (float)UniqueNewtStatueCount() / 8f; + } + + private static bool IsUnlockableNewtStatue(UnlockableDef unlockableDef) + { + return unlockableDef.cachedName.StartsWith("NewtStatue."); + } + + private int UniqueNewtStatueCount() + { + StatSheet statSheet = base.userProfile.statSheet; + int num = 0; + int i = 0; + for (int unlockableCount = statSheet.GetUnlockableCount(); i < unlockableCount; i++) + { + if (IsUnlockableNewtStatue(statSheet.GetUnlockable(i))) + { + num++; + } + } + return num; + } + + private void Check() + { + if (UniqueNewtStatueCount() >= 8) + { + Grant(); + } + } + + private void OnUnlockCheck(UserProfile userProfile, UnlockableDef unlockableDef) + { + if (userProfile == base.userProfile && IsUnlockableNewtStatue(unlockableDef)) + { + Check(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/FreeMageAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/FreeMageAchievement.cs new file mode 100644 index 0000000..1295eaa --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/FreeMageAchievement.cs @@ -0,0 +1,42 @@ +using EntityStates.LockedMage; + +namespace RoR2.Achievements; + +[RegisterAchievement("FreeMage", "Characters.Mage", null, 3u, typeof(FreeMageServerAchievement))] +public class FreeMageAchievement : BaseAchievement +{ + private class FreeMageServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + UnlockingMage.onOpened += OnOpened; + } + + public override void OnUninstall() + { + base.OnInstall(); + UnlockingMage.onOpened -= OnOpened; + } + + private void OnOpened(Interactor interactor) + { + CharacterBody currentBody = serverAchievementTracker.networkUser.GetCurrentBody(); + if ((bool)currentBody && currentBody.GetComponent() == interactor) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/HardEliteBossKillAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/HardEliteBossKillAchievement.cs new file mode 100644 index 0000000..2d924c5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/HardEliteBossKillAchievement.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RoR2.Achievements; + +[RegisterAchievement("HardEliteBossKill", "Items.KillEliteFrenzy", null, 3u, typeof(EliteBossKillServerAchievement))] +internal class HardEliteBossKillAchievement : BaseAchievement +{ + private class EliteBossKillServerAchievement : BaseServerAchievement + { + private static readonly List instancesList = new List(); + + public override void OnInstall() + { + base.OnInstall(); + instancesList.Add(this); + if (instancesList.Count == 1) + { + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + } + + public override void OnUninstall() + { + if (instancesList.Count == 1) + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + } + instancesList.Remove(this); + base.OnUninstall(); + } + + private static void OnCharacterDeath(DamageReport damageReport) + { + if (!damageReport.victim) + { + return; + } + CharacterBody body = damageReport.victim.body; + if (!body || !body.isChampion || !body.isElite) + { + return; + } + foreach (EliteBossKillServerAchievement instances in instancesList) + { + GameObject masterObject = instances.serverAchievementTracker.networkUser.masterObject; + if (!masterObject) + { + continue; + } + CharacterMaster component = masterObject.GetComponent(); + if ((bool)component) + { + CharacterBody body2 = component.GetBody(); + if ((bool)body2 && (bool)body2.healthComponent && body2.healthComponent.alive) + { + instances.Grant(); + } + } + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + NetworkUser.OnPostNetworkUserStart += OnPostNetworkUserStart; + Run.onRunStartGlobal += OnRunStart; + } + + public override void OnUninstall() + { + NetworkUser.OnPostNetworkUserStart -= OnPostNetworkUserStart; + Run.onRunStartGlobal -= OnRunStart; + base.OnUninstall(); + } + + private void UpdateTracking() + { + SetServerTracked((bool)Run.instance && (DifficultyCatalog.GetDifficultyDef(Run.instance.selectedDifficulty)?.countsAsHardMode ?? false)); + } + + private void OnPostNetworkUserStart(NetworkUser networkUser) + { + UpdateTracking(); + } + + private void OnRunStart(Run run) + { + UpdateTracking(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/HardHitterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/HardHitterAchievement.cs new file mode 100644 index 0000000..15609e4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/HardHitterAchievement.cs @@ -0,0 +1,27 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("HardHitter", "Items.ShockNearby", null, 3u, null)] +public class HardHitterAchievement : BaseAchievement +{ + private const float requirement = 5000f; + + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onClientDamageNotified += CheckDamage; + } + + public override void OnUninstall() + { + GlobalEventManager.onClientDamageNotified -= CheckDamage; + base.OnUninstall(); + } + + public void CheckDamage(DamageDealtMessage damageDealtMessage) + { + if (damageDealtMessage.damage >= 5000f && (bool)damageDealtMessage.attacker && damageDealtMessage.attacker == base.localUser.cachedBodyObject) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillBossQuantityInRunAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillBossQuantityInRunAchievement.cs new file mode 100644 index 0000000..1bf45a6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillBossQuantityInRunAchievement.cs @@ -0,0 +1,46 @@ +using System; +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("KillBossQuantityInRun", "Items.LunarSkillReplacements", null, 2u, null)] +public class KillBossQuantityInRunAchievement : BaseAchievement +{ + private static readonly ulong requirement = 15uL; + + private PlayerStatsComponent playerStatsComponent; + + public override void OnInstall() + { + base.OnInstall(); + base.localUser.onMasterChanged += OnMasterChanged; + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(OnStatsReceived)); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(OnStatsReceived)); + base.localUser.onMasterChanged -= OnMasterChanged; + base.OnUninstall(); + } + + private void OnMasterChanged() + { + playerStatsComponent = base.localUser.cachedMasterController?.GetComponent(); + } + + private void OnStatsReceived() + { + Check(); + } + + private void Check() + { + if (playerStatsComponent != null && requirement <= playerStatsComponent.currentStats.GetStatValueULong(StatDef.totalTeleporterBossKillsWitnessed)) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillBossQuickAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillBossQuickAchievement.cs new file mode 100644 index 0000000..826af36 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillBossQuickAchievement.cs @@ -0,0 +1,41 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("KillBossQuick", "Items.TreasureCache", null, 1u, typeof(KillBossQuickServerAchievement))] +public class KillBossQuickAchievement : BaseAchievement +{ + private class KillBossQuickServerAchievement : BaseServerAchievement + { + private const float requirement = 15f; + + public override void OnInstall() + { + base.OnInstall(); + BossGroup.onBossGroupDefeatedServer += OnBossGroupDefeatedServer; + } + + public override void OnUninstall() + { + BossGroup.onBossGroupDefeatedServer -= OnBossGroupDefeatedServer; + base.OnUninstall(); + } + + private void OnBossGroupDefeatedServer(BossGroup bossGroup) + { + if (bossGroup.fixedTimeSinceEnabled <= 15f && (bool)bossGroup.GetComponent()) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillElementalLemuriansAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillElementalLemuriansAchievement.cs new file mode 100644 index 0000000..38ab560 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillElementalLemuriansAchievement.cs @@ -0,0 +1,15 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("KillElementalLemurians", "Items.ElementalRings", null, 2u, typeof(KillElementalLemuriansServerAchievement))] +public class KillElementalLemuriansAchievement : BaseAchievement +{ + private class KillElementalLemuriansServerAchievement : BaseServerAchievement + { + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillEliteMonsterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillEliteMonsterAchievement.cs new file mode 100644 index 0000000..0184ad1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillEliteMonsterAchievement.cs @@ -0,0 +1,40 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("KillEliteMonster", "Items.Medkit", null, 1u, typeof(KillEliteMonsterServerAchievement))] +public class KillEliteMonsterAchievement : BaseAchievement +{ + private class KillEliteMonsterServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if (damageReport.victimIsElite && (bool)damageReport.attackerMaster && damageReport.attackerMaster.gameObject == serverAchievementTracker.networkUser.masterObject) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + SetServerTracked(shouldTrack: false); + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillElitesMilestoneAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillElitesMilestoneAchievement.cs new file mode 100644 index 0000000..59e8c65 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillElitesMilestoneAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("KillElitesMilestone", "Items.ExecuteLowHealthElite", null, 2u, null)] +public class KillElitesMilestoneAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalEliteKills; + + protected override ulong statRequirement => 500uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillGoldTitanInOneCycleAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillGoldTitanInOneCycleAchievement.cs new file mode 100644 index 0000000..d7d569a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillGoldTitanInOneCycleAchievement.cs @@ -0,0 +1,45 @@ +using EntityStates.Missions.Goldshores; + +namespace RoR2.Achievements; + +[RegisterAchievement("KillGoldTitanInOneCycle", "Items.Gateway", null, 2u, typeof(KillGoldTitanInOnePhaseServerAchievement))] +public class KillGoldTitanInOneCycleAchievement : BaseAchievement +{ + public class KillGoldTitanInOnePhaseServerAchievement : BaseServerAchievement + { + private BodyIndex goldTitanBodyIndex = BodyIndex.None; + + public override void OnInstall() + { + base.OnInstall(); + goldTitanBodyIndex = BodyCatalog.FindBodyIndex("TitanGoldBody"); + GoldshoresBossfight.onOneCycleGoldTitanKill += OnOneCycleGoldTitanKill; + } + + private void OnOneCycleGoldTitanKill() + { + if ((bool)serverAchievementTracker.networkUser.GetCurrentBody()) + { + Grant(); + } + } + + public override void OnUninstall() + { + GoldshoresBossfight.onOneCycleGoldTitanKill -= OnOneCycleGoldTitanKill; + base.OnUninstall(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + SetServerTracked(shouldTrack: false); + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/KillTotalEnemiesAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillTotalEnemiesAchievement.cs new file mode 100644 index 0000000..0538d20 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/KillTotalEnemiesAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("KillTotalEnemies", "Items.Infusion", null, 2u, null)] +public class KillTotalEnemiesAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalKills; + + protected override ulong statRequirement => 3000uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/LoaderBigSlamAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/LoaderBigSlamAchievement.cs new file mode 100644 index 0000000..c5dd5c8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/LoaderBigSlamAchievement.cs @@ -0,0 +1,51 @@ +using Assets.RoR2.Scripts.Platform; +using EntityStates.Loader; +using UnityEngine; + +namespace RoR2.Achievements; + +[RegisterAchievement("LoaderBigSlam", "Skills.Loader.ZapFist", "DefeatSuperRoboBallBoss", 3u, null)] +public class LoaderBigSlamAchievement : BaseAchievement +{ + private static readonly float requirement = (float)(300.0 * HGUnitConversions.milesToMeters / (1.0 * HGUnitConversions.hoursToSeconds)); + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("LoaderBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + BaseSwingChargedFist.onHitAuthorityGlobal += SwingChargedFistOnOnHitAuthorityGlobal; + } + + protected override void OnBodyRequirementBroken() + { + BaseSwingChargedFist.onHitAuthorityGlobal -= SwingChargedFistOnOnHitAuthorityGlobal; + base.OnBodyRequirementBroken(); + } + + public override void TryToCompleteActivity() + { + if (base.localUser.id == LocalUserManager.GetFirstLocalUser().id && shouldGrant) + { + BaseActivitySelector baseActivitySelector = new BaseActivitySelector(); + baseActivitySelector.activityAchievementID = "LoaderBigSlam"; + PlatformSystems.activityManager.TryToCompleteActivity(baseActivitySelector); + } + } + + private void SwingChargedFistOnOnHitAuthorityGlobal(BaseSwingChargedFist state) + { + if ((object)state.outer.commonComponents.characterBody == base.localUser.cachedBody) + { + Debug.LogFormat("{0}/{1}", state.punchSpeed, requirement); + if (state.punchSpeed >= requirement) + { + Grant(); + TryToCompleteActivity(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/LoaderKillLoadersAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/LoaderKillLoadersAchievement.cs new file mode 100644 index 0000000..63fe872 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/LoaderKillLoadersAchievement.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; + +namespace RoR2.Achievements; + +[RegisterAchievement("LoaderKillLoaders", "Skills.Loader.Thunderslam", "DefeatSuperRoboBallBoss", 3u, typeof(LoaderKillLoadersServerAchievement))] +public class LoaderKillLoadersAchievement : BaseAchievement +{ + private class LoaderKillLoadersServerAchievement : BaseServerAchievement + { + private BodyIndex bodyIndex; + + private List requiredSceneDefs = new List(); + + private int numKills; + + public override void OnInstall() + { + base.OnInstall(); + bodyIndex = BodyCatalog.FindBodyIndex("LoaderBody"); + requiredSceneDefs.Add(SceneCatalog.GetSceneDefFromSceneName("artifactworld")); + requiredSceneDefs.Add(SceneCatalog.GetSceneDefFromSceneName("artifactworld01")); + requiredSceneDefs.Add(SceneCatalog.GetSceneDefFromSceneName("artifactworld02")); + requiredSceneDefs.Add(SceneCatalog.GetSceneDefFromSceneName("artifactworld03")); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if ((bool)damageReport.victimBody) + { + if (damageReport.victimBody.bodyIndex == bodyIndex && IsCurrentBody(damageReport.attackerBody) && CheckForArtifactWorldScene()) + { + numKills++; + } + if (numKills >= 3) + { + Grant(); + } + } + } + + private bool CheckForArtifactWorldScene() + { + bool result = false; + for (int i = 0; i < requiredSceneDefs.Count; i++) + { + if (SceneCatalog.mostRecentSceneDef == requiredSceneDefs[i]) + { + result = true; + break; + } + } + return result; + } + } + + private const int requirement = 3; + + protected override BodyIndex LookUpRequiredBodyIndex() + { + return BodyCatalog.FindBodyIndex("LoaderBody"); + } + + protected override void OnBodyRequirementMet() + { + base.OnBodyRequirementMet(); + SetServerTracked(shouldTrack: true); + } + + protected override void OnBodyRequirementBroken() + { + SetServerTracked(shouldTrack: false); + base.OnBodyRequirementBroken(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/LogCollectorAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/LogCollectorAchievement.cs new file mode 100644 index 0000000..8555b9d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/LogCollectorAchievement.cs @@ -0,0 +1,63 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("LogCollector", "Items.Scanner", null, 2u, null)] +public class LogCollectorAchievement : BaseAchievement +{ + private const int requirement = 10; + + public override void OnInstall() + { + base.OnInstall(); + Check(); + UserProfile.onUnlockableGranted += OnUnlockCheck; + } + + public override void OnUninstall() + { + UserProfile.onUnlockableGranted -= OnUnlockCheck; + base.OnUninstall(); + } + + public override float ProgressForAchievement() + { + return (float)MonsterLogCount() / 10f; + } + + private static bool IsUnlockableMonsterLog(UnlockableDef unlockableDef) + { + return unlockableDef.cachedName.StartsWith("Logs."); + } + + private int MonsterLogCount() + { + StatSheet statSheet = base.userProfile.statSheet; + int num = 0; + int i = 0; + for (int unlockableCount = statSheet.GetUnlockableCount(); i < unlockableCount; i++) + { + if (IsUnlockableMonsterLog(statSheet.GetUnlockable(i))) + { + num++; + } + } + return num; + } + + private void Check() + { + if (MonsterLogCount() >= 10) + { + Grant(); + } + } + + private void OnUnlockCheck(UserProfile userProfile, UnlockableDef unlockableDef) + { + if (userProfile == base.userProfile && IsUnlockableMonsterLog(unlockableDef)) + { + Check(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/LoopOnceAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/LoopOnceAchievement.cs new file mode 100644 index 0000000..6d475eb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/LoopOnceAchievement.cs @@ -0,0 +1,34 @@ +using System; + +namespace RoR2.Achievements; + +[RegisterAchievement("LoopOnce", "Items.BounceNearby", null, 3u, null)] +public class LoopOnceAchievement : BaseAchievement +{ + public override void OnInstall() + { + base.OnInstall(); + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(Check)); + Check(); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(Check)); + base.OnUninstall(); + } + + private void Check() + { + if ((bool)Run.instance && Run.instance.GetType() == typeof(Run) && Run.instance.loopClearCount > 0) + { + SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); + if ((bool)sceneDefForCurrentScene && (sceneDefForCurrentScene.sceneType == SceneType.Stage || sceneDefForCurrentScene.sceneType == SceneType.UntimedStage) && !sceneDefForCurrentScene.isFinalStage && sceneDefForCurrentScene.stageOrder == 1) + { + Grant(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/MajorMultikillAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/MajorMultikillAchievement.cs new file mode 100644 index 0000000..6e18ff5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/MajorMultikillAchievement.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +namespace RoR2.Achievements; + +[RegisterAchievement("MajorMultikill", "Items.BurnNearby", null, 2u, typeof(MajorMultikillServerAchievement))] +public class MajorMultikillAchievement : BaseAchievement +{ + private class MajorMultikillServerAchievement : BaseServerAchievement + { + private const int multiKillThreshold = 15; + + public override void OnInstall() + { + base.OnInstall(); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + GameObject attacker = damageReport.damageInfo.attacker; + if ((bool)attacker) + { + CharacterBody component = attacker.GetComponent(); + if ((bool)component && component.multiKillCount >= 15 && component.masterObject == serverAchievementTracker.networkUser.masterObject) + { + Grant(); + } + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/MaxHealingShrineAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/MaxHealingShrineAchievement.cs new file mode 100644 index 0000000..8b8f3f8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/MaxHealingShrineAchievement.cs @@ -0,0 +1,45 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("MaxHealingShrine", "Items.PassiveHealing", null, 1u, typeof(MaxHealingShrineServerAchievement))] +public class MaxHealingShrineAchievement : BaseAchievement +{ + private class MaxHealingShrineServerAchievement : BaseServerAchievement + { + private const int requirement = 2; + + public override void OnInstall() + { + base.OnInstall(); + ShrineHealingBehavior.onActivated += OnHealingShrineActivated; + } + + public override void OnUninstall() + { + ShrineHealingBehavior.onActivated -= OnHealingShrineActivated; + base.OnUninstall(); + } + + private void OnHealingShrineActivated(ShrineHealingBehavior shrine, Interactor activator) + { + if (shrine.purchaseCount >= shrine.maxPurchaseCount) + { + CharacterBody currentBody = GetCurrentBody(); + if ((bool)currentBody && currentBody.gameObject == activator.gameObject) + { + Grant(); + } + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/MeridianEventTriggerAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/MeridianEventTriggerAchievement.cs new file mode 100644 index 0000000..a3d622d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/MeridianEventTriggerAchievement.cs @@ -0,0 +1,26 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements; + +public class MeridianEventTriggerAchievement : BaseAchievement +{ + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonDeathEvent += OnMeridianEventTriggerActivated; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonDeathEvent -= OnMeridianEventTriggerActivated; + } + + private void OnMeridianEventTriggerActivated() + { + if (base.isUserAlive) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/MoveSpeedAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/MoveSpeedAchievement.cs new file mode 100644 index 0000000..3f3a29c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/MoveSpeedAchievement.cs @@ -0,0 +1,27 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("MoveSpeed", "Items.JumpBoost", null, 2u, null)] +public class MoveSpeedAchievement : BaseAchievement +{ + private const float requirement = 4f; + + public override void OnInstall() + { + base.OnInstall(); + RoR2Application.onUpdate += CheckMoveSpeed; + } + + public override void OnUninstall() + { + RoR2Application.onUpdate -= CheckMoveSpeed; + base.OnUninstall(); + } + + public void CheckMoveSpeed() + { + if (base.localUser != null && (bool)base.localUser.cachedBody && base.localUser.cachedBody.moveSpeed / base.localUser.cachedBody.baseMoveSpeed >= 4f) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/MultiCombatShrineAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/MultiCombatShrineAchievement.cs new file mode 100644 index 0000000..15d61c5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/MultiCombatShrineAchievement.cs @@ -0,0 +1,57 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("MultiCombatShrine", "Items.EnergizedOnEquipmentUse", null, 2u, typeof(MultiCombatShrineServerAchievement))] +public class MultiCombatShrineAchievement : BaseAchievement +{ + private class MultiCombatShrineServerAchievement : BaseServerAchievement + { + private int counter; + + private static readonly int requirement = 3; + + public override void OnInstall() + { + base.OnInstall(); + ShrineCombatBehavior.onDefeatedServerGlobal += OnShrineDefeated; + Stage.onServerStageBegin += OnServerStageBegin; + } + + public override void OnUninstall() + { + Stage.onServerStageBegin -= OnServerStageBegin; + ShrineCombatBehavior.onDefeatedServerGlobal -= OnShrineDefeated; + base.OnUninstall(); + } + + private void OnServerStageBegin(Stage stage) + { + counter = 0; + } + + private void OnShrineDefeated(ShrineCombatBehavior instance) + { + counter++; + Check(); + } + + private void Check() + { + if (counter >= requirement) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + SetServerTracked(shouldTrack: false); + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/NeverBackDown.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/NeverBackDown.cs new file mode 100644 index 0000000..af7ff38 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/NeverBackDown.cs @@ -0,0 +1,95 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("NeverBackDown", "Items.FocusConvergence", null, 2u, typeof(NeverBackDown))] +public class NeverBackDown : BaseAchievement +{ + private bool _checkingForFailure; + + private static readonly int requirement = 4; + + private bool hasLeftRadius; + + private int levels; + + private Run.FixedTimeStamp teleporterStartChargingTime = Run.FixedTimeStamp.negativeInfinity; + + private static readonly float gracePeriod = 2f; + + private bool checkingForFailure + { + get + { + return _checkingForFailure; + } + set + { + if (_checkingForFailure != value) + { + _checkingForFailure = value; + if (_checkingForFailure) + { + RoR2Application.onFixedUpdate += CheckForFailure; + } + else + { + RoR2Application.onFixedUpdate -= CheckForFailure; + } + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + TeleporterInteraction.onTeleporterBeginChargingGlobal += OnTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged; + Run.onRunStartGlobal += OnRunStartGlobal; + } + + public override void OnUninstall() + { + checkingForFailure = false; + Run.onRunStartGlobal -= OnRunStartGlobal; + TeleporterInteraction.onTeleporterBeginChargingGlobal -= OnTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged; + base.OnUninstall(); + } + + private void OnRunStartGlobal(Run run) + { + levels = 0; + } + + private void OnTeleporterBeginCharging(TeleporterInteraction teleporterInteraction) + { + hasLeftRadius = false; + teleporterStartChargingTime = Run.FixedTimeStamp.now; + checkingForFailure = true; + } + + private void OnTeleporterCharged(TeleporterInteraction teleporterInteraction) + { + if (!hasLeftRadius) + { + levels++; + } + if (levels >= requirement) + { + Grant(); + } + } + + private void CheckForFailure() + { + if (!TeleporterInteraction.instance || TeleporterInteraction.instance.isCharged) + { + checkingForFailure = false; + } + else if ((bool)base.localUser.cachedBody && (teleporterStartChargingTime + gracePeriod).hasPassed && !TeleporterInteraction.instance.holdoutZoneController.IsBodyInChargingRadius(base.localUser.cachedBody)) + { + hasLeftRadius = true; + levels = 0; + checkingForFailure = false; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/RepeatFirstTeleporterAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/RepeatFirstTeleporterAchievement.cs new file mode 100644 index 0000000..3ae4c42 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/RepeatFirstTeleporterAchievement.cs @@ -0,0 +1,67 @@ +using System; +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("RepeatFirstTeleporter", "Characters.Toolbot", null, 3u, typeof(RepeatFirstTeleporterServerAchievement))] +public class RepeatFirstTeleporterAchievement : BaseAchievement +{ + private class RepeatFirstTeleporterServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterCharged; + } + + public override void OnUninstall() + { + TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterCharged; + base.OnUninstall(); + } + + private void OnTeleporterCharged(TeleporterInteraction teleporterInteraction) + { + SceneCatalog.GetSceneDefForCurrentScene(); + _ = base.networkUser.masterPlayerStatsComponent.currentStats; + if ((bool)Run.instance && Run.instance.stageClearCount == 0) + { + PlayerStatsComponent masterPlayerStatsComponent = base.networkUser.masterPlayerStatsComponent; + if ((bool)masterPlayerStatsComponent) + { + masterPlayerStatsComponent.currentStats.PushStatValue(StatDef.firstTeleporterCompleted, 1uL); + } + } + } + } + + private const int requirement = 5; + + public override void OnInstall() + { + base.OnInstall(); + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(Check)); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(Check)); + base.OnUninstall(); + } + + private void Check() + { + if (base.userProfile.statSheet.GetStatValueULong(StatDef.firstTeleporterCompleted) >= 5) + { + Grant(); + } + } + + public override float ProgressForAchievement() + { + return (float)base.userProfile.statSheet.GetStatValueULong(StatDef.firstTeleporterCompleted) / 5f; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/RepeatedlyDuplicateItemsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/RepeatedlyDuplicateItemsAchievement.cs new file mode 100644 index 0000000..e35cf01 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/RepeatedlyDuplicateItemsAchievement.cs @@ -0,0 +1,68 @@ +namespace RoR2.Achievements; + +[RegisterAchievement("RepeatedlyDuplicateItems", "Items.Firework", null, 1u, typeof(RepeatedlyDuplicateItemsServerAchievement))] +public class RepeatedlyDuplicateItemsAchievement : BaseAchievement +{ + private class RepeatedlyDuplicateItemsServerAchievement : BaseServerAchievement + { + private const int requirement = 7; + + private ItemIndex trackingItemIndex = ItemIndex.None; + + private int progress; + + public override void OnInstall() + { + base.OnInstall(); + PurchaseInteraction.onItemSpentOnPurchase += OnItemSpentOnPurchase; + Run.onRunStartGlobal += OnRunStartGlobal; + } + + public override void OnUninstall() + { + base.OnInstall(); + PurchaseInteraction.onItemSpentOnPurchase -= OnItemSpentOnPurchase; + Run.onRunStartGlobal -= OnRunStartGlobal; + } + + private void OnRunStartGlobal(Run run) + { + progress = 0; + } + + private void OnItemSpentOnPurchase(PurchaseInteraction purchaseInteraction, Interactor interactor) + { + CharacterBody currentBody = serverAchievementTracker.networkUser.GetCurrentBody(); + if (!currentBody || !(currentBody.GetComponent() == interactor) || !purchaseInteraction.gameObject.name.Contains("Duplicator")) + { + return; + } + ShopTerminalBehavior component = purchaseInteraction.GetComponent(); + if ((bool)component) + { + ItemIndex itemIndex = PickupCatalog.GetPickupDef(component.CurrentPickupIndex())?.itemIndex ?? ItemIndex.None; + if (trackingItemIndex != itemIndex) + { + trackingItemIndex = itemIndex; + progress = 0; + } + progress++; + if (progress >= 7) + { + Grant(); + } + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/RescueTreebotAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/RescueTreebotAchievement.cs new file mode 100644 index 0000000..89dbd9a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/RescueTreebotAchievement.cs @@ -0,0 +1,42 @@ +using EntityStates.Treebot.UnlockInteractable; + +namespace RoR2.Achievements; + +[RegisterAchievement("RescueTreebot", "Characters.Treebot", null, 3u, typeof(RescueTreebotServerAchievement))] +public class RescueTreebotAchievement : BaseAchievement +{ + public class RescueTreebotServerAchievement : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + Unlock.onActivated += OnActivated; + } + + public override void OnUninstall() + { + Unlock.onActivated -= OnActivated; + base.OnInstall(); + } + + private void OnActivated(Interactor interactor) + { + CharacterBody currentBody = serverAchievementTracker.networkUser.GetCurrentBody(); + if ((bool)currentBody && currentBody.GetComponent() == interactor) + { + Grant(); + } + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/ServerAchievementTracker.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/ServerAchievementTracker.cs new file mode 100644 index 0000000..77f6857 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/ServerAchievementTracker.cs @@ -0,0 +1,253 @@ +using Unity; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Achievements; + +[RequireComponent(typeof(NetworkUser))] +public class ServerAchievementTracker : NetworkBehaviour +{ + private BaseServerAchievement[] achievementTrackers; + + private SerializableBitArray maskBitArrayConverter; + + private byte[] maskBuffer; + + private static int kCmdCmdSetAchievementTrackerRequests; + + private static int kRpcRpcGrantAchievement; + + private static int kRpcRpcTryToCompleteActivity; + + public NetworkUser networkUser { get; private set; } + + private void Awake() + { + networkUser = GetComponent(); + maskBitArrayConverter = new SerializableBitArray(AchievementManager.serverAchievementCount); + if (NetworkServer.active) + { + achievementTrackers = new BaseServerAchievement[AchievementManager.serverAchievementCount]; + } + if (NetworkClient.active) + { + maskBuffer = new byte[maskBitArrayConverter.byteCount]; + } + } + + private void Start() + { + if (networkUser.localUser != null) + { + AchievementManager.GetUserAchievementManager(networkUser.localUser)?.TransmitAchievementRequestsToServer(); + } + } + + private void OnDestroy() + { + if (achievementTrackers != null) + { + int serverAchievementCount = AchievementManager.serverAchievementCount; + for (int i = 0; i < serverAchievementCount; i++) + { + SetAchievementTracked(new ServerAchievementIndex + { + intValue = i + }, shouldTrack: false); + } + } + } + + [Client] + public void SendAchievementTrackerRequestsMaskToServer(bool[] serverAchievementsToTrackMask) + { + if (!NetworkClient.active) + { + Debug.LogWarning("[Client] function 'System.Void RoR2.Achievements.ServerAchievementTracker::SendAchievementTrackerRequestsMaskToServer(System.Boolean[])' called on server"); + return; + } + int serverAchievementCount = AchievementManager.serverAchievementCount; + for (int i = 0; i < serverAchievementCount; i++) + { + maskBitArrayConverter[i] = serverAchievementsToTrackMask[i]; + } + maskBitArrayConverter.GetBytes(maskBuffer); + CallCmdSetAchievementTrackerRequests(maskBuffer); + } + + [Command] + private void CmdSetAchievementTrackerRequests(byte[] packedServerAchievementsToTrackMask) + { + int serverAchievementCount = AchievementManager.serverAchievementCount; + if (packedServerAchievementsToTrackMask.Length << 3 >= serverAchievementCount) + { + for (int i = 0; i < serverAchievementCount; i++) + { + int num = i >> 3; + int num2 = i & 7; + SetAchievementTracked(new ServerAchievementIndex + { + intValue = i + }, ((packedServerAchievementsToTrackMask[num] >> num2) & 1) != 0); + } + } + } + + private void SetAchievementTracked(ServerAchievementIndex serverAchievementIndex, bool shouldTrack) + { + BaseServerAchievement baseServerAchievement = achievementTrackers[serverAchievementIndex.intValue]; + if (shouldTrack != (baseServerAchievement != null)) + { + if (shouldTrack) + { + BaseServerAchievement baseServerAchievement2 = BaseServerAchievement.Instantiate(serverAchievementIndex); + baseServerAchievement2.serverAchievementTracker = this; + achievementTrackers[serverAchievementIndex.intValue] = baseServerAchievement2; + baseServerAchievement2.OnInstall(); + } + else + { + baseServerAchievement.OnUninstall(); + achievementTrackers[serverAchievementIndex.intValue] = null; + } + } + } + + [ClientRpc] + public void RpcGrantAchievement(ServerAchievementIndex serverAchievementIndex) + { + LocalUser localUser = networkUser.localUser; + if (localUser != null) + { + AchievementManager.GetUserAchievementManager(localUser)?.HandleServerAchievementCompleted(serverAchievementIndex); + } + } + + [ClientRpc] + public void RpcTryToCompleteActivity(ServerAchievementIndex serverAchievementIndex) + { + LocalUser localUser = networkUser.localUser; + if (localUser != null) + { + AchievementManager.GetUserAchievementManager(localUser)?.HandleServerTryToCompleteActivity(serverAchievementIndex); + } + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdSetAchievementTrackerRequests(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdSetAchievementTrackerRequests called on client."); + } + else + { + ((ServerAchievementTracker)obj).CmdSetAchievementTrackerRequests(reader.ReadBytesAndSize()); + } + } + + public void CallCmdSetAchievementTrackerRequests(byte[] packedServerAchievementsToTrackMask) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdSetAchievementTrackerRequests called on server."); + return; + } + if (base.isServer) + { + CmdSetAchievementTrackerRequests(packedServerAchievementsToTrackMask); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdSetAchievementTrackerRequests); + networkWriter.Write(GetComponent().netId); + networkWriter.WriteBytesFull(packedServerAchievementsToTrackMask); + SendCommandInternal(networkWriter, 0, "CmdSetAchievementTrackerRequests"); + } + + protected static void InvokeRpcRpcGrantAchievement(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkClient.active) + { + Debug.LogError("RPC RpcGrantAchievement called on server."); + } + else + { + ((ServerAchievementTracker)obj).RpcGrantAchievement(GeneratedNetworkCode._ReadServerAchievementIndex_None(reader)); + } + } + + protected static void InvokeRpcRpcTryToCompleteActivity(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkClient.active) + { + Debug.LogError("RPC RpcTryToCompleteActivity called on server."); + } + else + { + ((ServerAchievementTracker)obj).RpcTryToCompleteActivity(GeneratedNetworkCode._ReadServerAchievementIndex_None(reader)); + } + } + + public void CallRpcGrantAchievement(ServerAchievementIndex serverAchievementIndex) + { + if (!NetworkServer.active) + { + Debug.LogError("RPC Function RpcGrantAchievement called on client."); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)2); + networkWriter.WritePackedUInt32((uint)kRpcRpcGrantAchievement); + networkWriter.Write(GetComponent().netId); + GeneratedNetworkCode._WriteServerAchievementIndex_None(networkWriter, serverAchievementIndex); + SendRPCInternal(networkWriter, 0, "RpcGrantAchievement"); + } + + public void CallRpcTryToCompleteActivity(ServerAchievementIndex serverAchievementIndex) + { + if (!NetworkServer.active) + { + Debug.LogError("RPC Function RpcTryToCompleteActivity called on client."); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)2); + networkWriter.WritePackedUInt32((uint)kRpcRpcTryToCompleteActivity); + networkWriter.Write(GetComponent().netId); + GeneratedNetworkCode._WriteServerAchievementIndex_None(networkWriter, serverAchievementIndex); + SendRPCInternal(networkWriter, 0, "RpcTryToCompleteActivity"); + } + + static ServerAchievementTracker() + { + kCmdCmdSetAchievementTrackerRequests = 387052099; + NetworkBehaviour.RegisterCommandDelegate(typeof(ServerAchievementTracker), kCmdCmdSetAchievementTrackerRequests, InvokeCmdCmdSetAchievementTrackerRequests); + kRpcRpcGrantAchievement = -1713740939; + NetworkBehaviour.RegisterRpcDelegate(typeof(ServerAchievementTracker), kRpcRpcGrantAchievement, InvokeRpcRpcGrantAchievement); + kRpcRpcTryToCompleteActivity = -1526039716; + NetworkBehaviour.RegisterRpcDelegate(typeof(ServerAchievementTracker), kRpcRpcTryToCompleteActivity, InvokeRpcRpcTryToCompleteActivity); + NetworkCRC.RegisterBehaviour("ServerAchievementTracker", 0); + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool result = default(bool); + return result; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/StayAlive1Achievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/StayAlive1Achievement.cs new file mode 100644 index 0000000..2eb8da6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/StayAlive1Achievement.cs @@ -0,0 +1,40 @@ +using System.Linq; +using UnityEngine; + +namespace RoR2.Achievements; + +[RegisterAchievement("StayAlive1", "Items.ExtraLife", null, 3u, null)] +public class StayAlive1Achievement : BaseAchievement +{ + private const float requirement = 1800f; + + public override void OnInstall() + { + base.OnInstall(); + RoR2Application.onUpdate += Check; + } + + public override void OnUninstall() + { + RoR2Application.onUpdate -= Check; + base.OnUninstall(); + } + + private void Check() + { + NetworkUser networkUser = NetworkUser.readOnlyLocalPlayersList.FirstOrDefault((NetworkUser v) => v.localUser == base.localUser); + if (!networkUser) + { + return; + } + GameObject masterObject = networkUser.masterObject; + if ((bool)masterObject) + { + CharacterMaster component = masterObject.GetComponent(); + if ((bool)component && component.currentLifeStopwatch >= 1800f) + { + Grant(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/SuicideHermitCrabsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/SuicideHermitCrabsAchievement.cs new file mode 100644 index 0000000..d9ab080 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/SuicideHermitCrabsAchievement.cs @@ -0,0 +1,74 @@ +using System; +using RoR2.Stats; +using UnityEngine; + +namespace RoR2.Achievements; + +[RegisterAchievement("SuicideHermitCrabs", "Items.AutoCastEquipment", null, 2u, typeof(SuicideHermitCrabsServerAchievement))] +public class SuicideHermitCrabsAchievement : BaseAchievement +{ + private class SuicideHermitCrabsServerAchievement : BaseServerAchievement + { + private BodyIndex crabBodyIndex; + + public override void OnInstall() + { + base.OnInstall(); + crabBodyIndex = BodyCatalog.FindBodyIndex("HermitCrabBody"); + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + } + + public override void OnUninstall() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; + base.OnUninstall(); + } + + private void OnCharacterDeath(DamageReport damageReport) + { + if (!damageReport.victimBody || damageReport.victimBody.bodyIndex != crabBodyIndex || damageReport.victimBody.teamComponent.teamIndex == TeamIndex.Player) + { + return; + } + GameObject inflictor = damageReport.damageInfo.inflictor; + if ((bool)inflictor && (bool)inflictor.GetComponent()) + { + PlayerStatsComponent masterPlayerStatsComponent = base.networkUser.masterPlayerStatsComponent; + if ((bool)masterPlayerStatsComponent) + { + masterPlayerStatsComponent.currentStats.PushStatValue(StatDef.suicideHermitCrabsAchievementProgress, 1uL); + } + } + } + } + + private const int requirement = 20; + + public override void OnInstall() + { + base.OnInstall(); + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(Check)); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(Check)); + base.OnUninstall(); + } + + private void Check() + { + if (base.userProfile.statSheet.GetStatValueULong(StatDef.suicideHermitCrabsAchievementProgress) >= 20) + { + Grant(); + } + } + + public override float ProgressForAchievement() + { + return (float)base.userProfile.statSheet.GetStatValueULong(StatDef.suicideHermitCrabsAchievementProgress) / 20f; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/TotalDronesRepairedAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/TotalDronesRepairedAchievement.cs new file mode 100644 index 0000000..baf8cc5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/TotalDronesRepairedAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("TotalDronesRepaired", "Items.DroneBackup", null, 3u, null)] +public class TotalDronesRepairedAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.totalDronesPurchased; + + protected override ulong statRequirement => 30uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/TotalMoneyCollectedAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/TotalMoneyCollectedAchievement.cs new file mode 100644 index 0000000..e7225eb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/TotalMoneyCollectedAchievement.cs @@ -0,0 +1,11 @@ +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("TotalMoneyCollected", "Items.GoldGat", null, 2u, null)] +public class TotalMoneyCollectedAchievement : BaseStatMilestoneAchievement +{ + protected override StatDef statDef => StatDef.goldCollected; + + protected override ulong statRequirement => 30480uL; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/UnlockFalseSonAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/UnlockFalseSonAchievement.cs new file mode 100644 index 0000000..8c666de --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/UnlockFalseSonAchievement.cs @@ -0,0 +1,38 @@ +using EntityStates.FalseSonBoss; + +namespace RoR2.Achievements; + +[RegisterAchievement("UnlockFalseSon", "Characters.FalseSon", null, 3u, typeof(UnlockFalseSonAchievementServer))] +public class UnlockFalseSonAchievement : BaseAchievement +{ + public class UnlockFalseSonAchievementServer : BaseServerAchievement + { + public override void OnInstall() + { + base.OnInstall(); + SkyJumpDeathState.falseSonUnlockEvent += OnFalseSonUnlock; + } + + public override void OnUninstall() + { + base.OnUninstall(); + SkyJumpDeathState.falseSonUnlockEvent -= OnFalseSonUnlock; + } + + private void OnFalseSonUnlock() + { + Grant(); + } + } + + public override void OnInstall() + { + base.OnInstall(); + SetServerTracked(shouldTrack: true); + } + + public override void OnUninstall() + { + base.OnUninstall(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Achievements/UseThreePortalsAchievement.cs b/ilspy_dump/ror2_csproj/RoR2.Achievements/UseThreePortalsAchievement.cs new file mode 100644 index 0000000..2beb8db --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Achievements/UseThreePortalsAchievement.cs @@ -0,0 +1,63 @@ +using System; +using RoR2.Stats; + +namespace RoR2.Achievements; + +[RegisterAchievement("UseThreePortals", "Items.Tonic", null, 2u, null)] +public class UseThreePortalsAchievement : BaseAchievement +{ + private StatDef[] statsToCheck; + + private const int requirement = 3; + + public override void OnInstall() + { + base.OnInstall(); + statsToCheck = new StatDef[5] + { + PerStageStatDef.totalTimesVisited.FindStatDef("bazaar"), + PerStageStatDef.totalTimesVisited.FindStatDef("mysteryspace"), + PerStageStatDef.totalTimesVisited.FindStatDef("goldshores"), + PerStageStatDef.totalTimesVisited.FindStatDef("arena"), + PerStageStatDef.totalTimesVisited.FindStatDef("artifactworld") + }; + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Combine(obj.onStatsReceived, new Action(Check)); + Check(); + } + + public override void OnUninstall() + { + UserProfile obj = base.userProfile; + obj.onStatsReceived = (Action)Delegate.Remove(obj.onStatsReceived, new Action(Check)); + base.OnUninstall(); + } + + public override float ProgressForAchievement() + { + return (float)GetUniquePortalsUsedCount() / 3f; + } + + private int GetUniquePortalsUsedCount() + { + StatSheet statSheet = base.userProfile.statSheet; + int num = 0; + StatDef[] array = statsToCheck; + foreach (StatDef statDef in array) + { + if (statSheet.GetStatValueULong(statDef) != 0) + { + num++; + } + } + return num; + } + + private void Check() + { + if (GetUniquePortalsUsedCount() >= 3) + { + Grant(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/BombArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/BombArtifactManager.cs new file mode 100644 index 0000000..1d20d8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/BombArtifactManager.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using RoR2.ConVar; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class BombArtifactManager +{ + private struct BombRequest + { + public Vector3 spawnPosition; + + public Vector3 raycastOrigin; + + public float bombBaseDamage; + + public GameObject attacker; + + public TeamIndex teamIndex; + + public float velocityY; + } + + private static FloatConVar cvSpiteBombCoefficient = new FloatConVar("spite_bomb_coefficient", ConVarFlags.Cheat, "0.5", "Multiplier for number of spite bombs."); + + private static GameObject bombPrefab; + + private static readonly int maxBombCount = 30; + + private static readonly float extraBombPerRadius = 4f; + + private static readonly float bombSpawnBaseRadius = 3f; + + private static readonly float bombSpawnRadiusCoefficient = 4f; + + private static readonly float bombDamageCoefficient = 1.5f; + + private static readonly Queue bombRequestQueue = new Queue(); + + private static readonly float bombBlastRadius = 7f; + + private static readonly float bombFuseTimeout = 8f; + + private static readonly float maxBombStepUpDistance = 8f; + + private static readonly float maxBombFallDistance = 60f; + + private static ArtifactDef myArtifact => RoR2Content.Artifacts.bombArtifactDef; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/SpiteBomb", delegate(GameObject operationResult) + { + bombPrefab = operationResult; + }); + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (NetworkServer.active && !(artifactDef != myArtifact)) + { + GlobalEventManager.onCharacterDeathGlobal += OnServerCharacterDeath; + RoR2Application.onFixedUpdate += ProcessBombQueue; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + bombRequestQueue.Clear(); + RoR2Application.onFixedUpdate -= ProcessBombQueue; + GlobalEventManager.onCharacterDeathGlobal -= OnServerCharacterDeath; + } + } + + private static void SpawnBomb(BombRequest bombRequest, float groundY) + { + Vector3 spawnPosition = bombRequest.spawnPosition; + if (spawnPosition.y < groundY + 4f) + { + spawnPosition.y = groundY + 4f; + } + Vector3 raycastOrigin = bombRequest.raycastOrigin; + raycastOrigin.y = groundY; + GameObject gameObject = UnityEngine.Object.Instantiate(bombPrefab, spawnPosition, UnityEngine.Random.rotation); + SpiteBombController component = gameObject.GetComponent(); + DelayBlast delayBlast = component.delayBlast; + TeamFilter component2 = gameObject.GetComponent(); + component.bouncePosition = raycastOrigin; + component.initialVelocityY = bombRequest.velocityY; + delayBlast.position = spawnPosition; + delayBlast.baseDamage = bombRequest.bombBaseDamage; + delayBlast.baseForce = 2300f; + delayBlast.attacker = bombRequest.attacker; + delayBlast.radius = bombBlastRadius; + delayBlast.crit = false; + delayBlast.procCoefficient = 0.75f; + delayBlast.maxTimer = bombFuseTimeout; + delayBlast.timerStagger = 0f; + delayBlast.falloffModel = BlastAttack.FalloffModel.None; + component2.teamIndex = bombRequest.teamIndex; + NetworkServer.Spawn(gameObject); + } + + private static void OnServerCharacterDeath(DamageReport damageReport) + { + if (damageReport.victimTeamIndex == TeamIndex.Monster) + { + CharacterBody victimBody = damageReport.victimBody; + Vector3 corePosition = victimBody.corePosition; + int num = Mathf.Min(maxBombCount, Mathf.CeilToInt(victimBody.bestFitRadius * extraBombPerRadius * cvSpiteBombCoefficient.value)); + for (int i = 0; i < num; i++) + { + Vector3 vector = UnityEngine.Random.insideUnitSphere * (bombSpawnBaseRadius + victimBody.bestFitRadius * bombSpawnRadiusCoefficient); + BombRequest bombRequest = default(BombRequest); + bombRequest.spawnPosition = corePosition; + bombRequest.raycastOrigin = corePosition + vector; + bombRequest.bombBaseDamage = victimBody.damage * bombDamageCoefficient; + bombRequest.attacker = victimBody.gameObject; + bombRequest.teamIndex = damageReport.victimTeamIndex; + bombRequest.velocityY = UnityEngine.Random.Range(5f, 25f); + BombRequest item = bombRequest; + bombRequestQueue.Enqueue(item); + } + } + } + + private static void ProcessBombQueue() + { + if (bombRequestQueue.Count > 0) + { + BombRequest bombRequest = bombRequestQueue.Dequeue(); + Ray ray = new Ray(bombRequest.raycastOrigin + new Vector3(0f, maxBombStepUpDistance, 0f), Vector3.down); + float maxDistance = maxBombStepUpDistance + maxBombFallDistance; + if (Physics.Raycast(ray, out var hitInfo, maxDistance, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + SpawnBomb(bombRequest, hitInfo.point.y); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/CommandArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/CommandArtifactManager.cs new file mode 100644 index 0000000..8888b84 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/CommandArtifactManager.cs @@ -0,0 +1,59 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class CommandArtifactManager +{ + public static GameObject commandCubePrefab; + + public static bool IsCommandArtifactEnabled => RunArtifactManager.instance.IsArtifactEnabled(myArtifact); + + private static ArtifactDef myArtifact => RoR2Content.Artifacts.commandArtifactDef; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/CommandCube", delegate(GameObject operationResult) + { + commandCubePrefab = operationResult; + }); + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact) && NetworkServer.active) + { + SceneDirector.onGenerateInteractableCardSelection += OnGenerateInteractableCardSelection; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + SceneDirector.onGenerateInteractableCardSelection -= OnGenerateInteractableCardSelection; + } + } + + private static void OnGenerateInteractableCardSelection(SceneDirector sceneDirector, DirectorCardCategorySelection dccs) + { + dccs.RemoveCardsThatFailFilter(DoesNotOfferChoice); + static bool DoesNotOfferChoice(DirectorCard card) + { + return !OffersChoice(card); + } + static bool OffersChoice(DirectorCard card) + { + GameObject prefab = card.spawnCard.prefab; + if (!prefab.GetComponent() && !prefab.GetComponent()) + { + return prefab.GetComponent(); + } + return true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/DevotionArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/DevotionArtifactManager.cs new file mode 100644 index 0000000..af67fea --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/DevotionArtifactManager.cs @@ -0,0 +1,55 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class DevotionArtifactManager +{ + private static ArtifactDef myArtifact; + + private static GameObject devotionArtifactManagerPrefab; + + public static DirectorCard lumerianEgg; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/DevotionArtifactInfo", delegate(GameObject operationResult) + { + devotionArtifactManagerPrefab = operationResult; + }); + myArtifact = CU8Content.Artifacts.Devotion; + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (NetworkServer.active && !(artifactDef != myArtifact)) + { + SceneDirector.onGenerateInteractableCardSelection += OnGenerateInteractableCardSelection; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + SceneDirector.onGenerateInteractableCardSelection -= OnGenerateInteractableCardSelection; + } + } + + private static void CalcCardWeight(DirectorCard card, ref float weight) + { + InteractableSpawnCard interactableSpawnCard = card.spawnCard as InteractableSpawnCard; + if (interactableSpawnCard != null) + { + weight *= interactableSpawnCard.weightScalarWhenSacrificeArtifactEnabled; + } + } + + private static void OnGenerateInteractableCardSelection(SceneDirector sceneDirector, DirectorCardCategorySelection dccs) + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/DoppelgangerInvasionManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/DoppelgangerInvasionManager.cs new file mode 100644 index 0000000..057fc8e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/DoppelgangerInvasionManager.cs @@ -0,0 +1,160 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public class DoppelgangerInvasionManager : MonoBehaviour +{ + private readonly float invasionInterval = 600f; + + private int previousInvasionCycle; + + private ulong seed; + + private Run run; + + private Xoroshiro128Plus treasureRng; + + private PickupDropTable dropTable; + + private bool artifactIsEnabled => RunArtifactManager.instance.IsArtifactEnabled(RoR2Content.Artifacts.shadowCloneArtifactDef); + + public static event Action onDoppelgangerDeath; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + Run.onRunStartGlobal += OnRunStartGlobal; + } + + private static void OnRunStartGlobal(Run run) + { + if (NetworkServer.active) + { + run.gameObject.AddComponent(); + } + } + + private void Start() + { + run = GetComponent(); + seed = run.seed; + treasureRng = new Xoroshiro128Plus(seed); + dropTable = LegacyResourcesAPI.Load("DropTables/dtDoppelganger"); + } + + private void OnEnable() + { + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + ArtifactTrialMissionController.onShellTakeDamageServer += OnArtifactTrialShellTakeDamageServer; + } + + private void OnDisable() + { + ArtifactTrialMissionController.onShellTakeDamageServer -= OnArtifactTrialShellTakeDamageServer; + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + } + + private void FixedUpdate() + { + int currentInvasionCycle = GetCurrentInvasionCycle(); + if (previousInvasionCycle < currentInvasionCycle) + { + previousInvasionCycle = currentInvasionCycle; + if (artifactIsEnabled) + { + PerformInvasion(new Xoroshiro128Plus(seed + (ulong)currentInvasionCycle)); + } + } + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + Inventory inventory = damageReport.victimMaster?.inventory; + if (!inventory) + { + return; + } + bool flag = damageReport.victimMaster.minionOwnership.ownerMaster; + if (inventory.GetItemCount(RoR2Content.Items.InvadingDoppelganger) > 0 && inventory.GetItemCount(RoR2Content.Items.ExtraLife) == 0 && inventory.GetItemCount(DLC1Content.Items.ExtraLifeVoid) == 0 && !flag && !damageReport.victimBody.HasBuff(DLC2Content.Buffs.ExtraLifeBuff) && damageReport.victimBody.equipmentSlot.equipmentIndex != DLC2Content.Equipment.HealAndRevive.equipmentIndex) + { + DoppelgangerInvasionManager.onDoppelgangerDeath?.Invoke(damageReport); + PickupIndex pickupIndex = dropTable.GenerateDrop(treasureRng); + if (!(pickupIndex == PickupIndex.none)) + { + PickupDropletController.CreatePickupDroplet(pickupIndex, damageReport.victimBody.corePosition, Vector3.up * 20f); + } + } + } + + private void OnArtifactTrialShellTakeDamageServer(ArtifactTrialMissionController missionController, DamageReport damageReport) + { + if (artifactIsEnabled && damageReport.victim.alive) + { + PerformInvasion(new Xoroshiro128Plus((ulong)damageReport.victim.health)); + } + } + + private int GetCurrentInvasionCycle() + { + return Mathf.FloorToInt(run.GetRunStopwatch() / invasionInterval); + } + + public static void PerformInvasion(Xoroshiro128Plus rng) + { + for (int num = CharacterMaster.readOnlyInstancesList.Count - 1; num >= 0; num--) + { + CharacterMaster characterMaster = CharacterMaster.readOnlyInstancesList[num]; + if (characterMaster.teamIndex == TeamIndex.Player && (bool)characterMaster.playerCharacterMasterController) + { + CreateDoppelganger(characterMaster, rng); + } + } + } + + private static void CreateDoppelganger(CharacterMaster srcCharacterMaster, Xoroshiro128Plus rng) + { + SpawnCard spawnCard = DoppelgangerSpawnCard.FromMaster(srcCharacterMaster); + if (!spawnCard) + { + return; + } + Transform coreTransform; + DirectorCore.MonsterSpawnDistance input; + if ((bool)TeleporterInteraction.instance) + { + coreTransform = TeleporterInteraction.instance.transform; + input = DirectorCore.MonsterSpawnDistance.Close; + } + else + { + coreTransform = srcCharacterMaster.GetBody().coreTransform; + input = DirectorCore.MonsterSpawnDistance.Far; + } + DirectorPlacementRule directorPlacementRule = new DirectorPlacementRule + { + spawnOnTarget = coreTransform, + placementMode = DirectorPlacementRule.PlacementMode.NearestNode + }; + DirectorCore.GetMonsterSpawnDistance(input, out directorPlacementRule.minDistance, out directorPlacementRule.maxDistance); + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(spawnCard, directorPlacementRule, rng); + directorSpawnRequest.teamIndexOverride = TeamIndex.Monster; + directorSpawnRequest.ignoreTeamMemberLimit = true; + CombatSquad combatSquad = null; + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult result) + { + if (!combatSquad) + { + combatSquad = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/Encounters/ShadowCloneEncounter")).GetComponent(); + } + combatSquad.AddMember(result.spawnedInstance.GetComponent()); + }); + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + if ((bool)combatSquad) + { + NetworkServer.Spawn(combatSquad.gameObject); + } + UnityEngine.Object.Destroy(spawnCard); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/DoppelgangerSpawnCard.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/DoppelgangerSpawnCard.cs new file mode 100644 index 0000000..d726288 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/DoppelgangerSpawnCard.cs @@ -0,0 +1,31 @@ +using RoR2.CharacterAI; +using UnityEngine; + +namespace RoR2.Artifacts; + +public class DoppelgangerSpawnCard : MasterCopySpawnCard +{ + public static DoppelgangerSpawnCard FromMaster(CharacterMaster srcCharacterMaster) + { + if (!srcCharacterMaster || !srcCharacterMaster.GetBody()) + { + return null; + } + DoppelgangerSpawnCard doppelgangerSpawnCard = ScriptableObject.CreateInstance(); + MasterCopySpawnCard.CopyDataFromMaster(doppelgangerSpawnCard, srcCharacterMaster, copyItems: true, copyEquipment: true); + doppelgangerSpawnCard.GiveItem(RoR2Content.Items.InvadingDoppelganger); + doppelgangerSpawnCard.onPreSpawnSetup = OnPreSpawnSetup; + return doppelgangerSpawnCard; + void OnPreSpawnSetup(CharacterMaster spawnedMaster) + { + BaseAI ai = spawnedMaster.GetComponent(); + CharacterBody srcBody = srcCharacterMaster.GetBody(); + ai.onBodyDiscovered += SetEnemyToOriginator; + void SetEnemyToOriginator(CharacterBody body) + { + ai.currentEnemy.gameObject = srcBody.gameObject; + ai.onBodyDiscovered -= SetEnemyToOriginator; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/EnigmaArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/EnigmaArtifactManager.cs new file mode 100644 index 0000000..6c22bbc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/EnigmaArtifactManager.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class EnigmaArtifactManager +{ + private static readonly Xoroshiro128Plus serverInitialEquipmentRng = new Xoroshiro128Plus(0uL); + + private static readonly Xoroshiro128Plus serverActivationEquipmentRng = new Xoroshiro128Plus(0uL); + + private static List validEquipment = new List(); + + private static BodyIndex toolbotBodyIndex = BodyIndex.None; + + private static ArtifactDef myArtifact => RoR2Content.Artifacts.enigmaArtifactDef; + + [SystemInitializer(new Type[] + { + typeof(ArtifactCatalog), + typeof(BodyCatalog) + })] + private static void Init() + { + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + Run.onRunStartGlobal += OnRunStartGlobal; + toolbotBodyIndex = BodyCatalog.FindBodyIndex("ToolbotBody"); + } + + private static void OnRunStartGlobal(Run run) + { + if (!NetworkServer.active) + { + return; + } + serverInitialEquipmentRng.ResetSeed(run.seed); + serverActivationEquipmentRng.ResetSeed(serverInitialEquipmentRng.nextUlong); + validEquipment.Clear(); + foreach (EquipmentIndex enigmaEquipment in EquipmentCatalog.enigmaEquipmentList) + { + EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(enigmaEquipment); + if ((bool)equipmentDef && (!equipmentDef.requiredExpansion || run.IsExpansionEnabled(equipmentDef.requiredExpansion))) + { + validEquipment.Add(enigmaEquipment); + } + } + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact) && NetworkServer.active) + { + CharacterBody.onBodyStartGlobal += OnBodyStartGlobalServer; + EquipmentSlot.onServerEquipmentActivated += OnServerEquipmentActivated; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + EquipmentSlot.onServerEquipmentActivated -= OnServerEquipmentActivated; + CharacterBody.onBodyStartGlobal -= OnBodyStartGlobalServer; + } + } + + private static void OnBodyStartGlobalServer(CharacterBody characterBody) + { + if (characterBody.isPlayerControlled) + { + OnPlayerCharacterBodyStartServer(characterBody); + } + } + + private static void OnPlayerCharacterBodyStartServer(CharacterBody characterBody) + { + Inventory inventory = characterBody.inventory; + int val = ((characterBody.bodyIndex != toolbotBodyIndex) ? 1 : 2); + int num = Math.Max(inventory.GetEquipmentSlotCount(), val); + for (int i = 0; i < num; i++) + { + if (inventory.GetEquipment((uint)i).equipmentIndex == EquipmentIndex.None) + { + EquipmentIndex randomEquipment = GetRandomEquipment(serverInitialEquipmentRng, (int)(i + characterBody.bodyIndex)); + EquipmentState equipmentState = new EquipmentState(randomEquipment, Run.FixedTimeStamp.negativeInfinity, 1); + inventory.SetEquipment(equipmentState, (uint)i); + } + } + } + + private static void OnServerEquipmentActivated(EquipmentSlot equipmentSlot, EquipmentIndex equipmentIndex) + { + EquipmentIndex randomEquipment = GetRandomEquipment(serverActivationEquipmentRng, (int)equipmentIndex); + equipmentSlot.characterBody.inventory.SetEquipmentIndex(randomEquipment); + } + + private static EquipmentIndex GetRandomEquipment(Xoroshiro128Plus rng, int offset) + { + int count = validEquipment.Count; + int num = rng.RangeInt(0, count); + num += offset; + num %= count; + return validEquipment[num]; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/FriendlyFireArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/FriendlyFireArtifactManager.cs new file mode 100644 index 0000000..51276b5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/FriendlyFireArtifactManager.cs @@ -0,0 +1,31 @@ +using System; + +namespace RoR2.Artifacts; + +public static class FriendlyFireArtifactManager +{ + private static ArtifactDef myArtifact => RoR2Content.Artifacts.friendlyFireArtifactDef; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabledGlobal; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabledGlobal; + } + + private static void OnArtifactEnabledGlobal(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + FriendlyFireManager.friendlyFireMode = FriendlyFireManager.FriendlyFireMode.FriendlyFire; + } + } + + private static void OnArtifactDisabledGlobal(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + FriendlyFireManager.friendlyFireMode = FriendlyFireManager.FriendlyFireMode.Off; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/MonsterTeamGainsItemsArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/MonsterTeamGainsItemsArtifactManager.cs new file mode 100644 index 0000000..85f877d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/MonsterTeamGainsItemsArtifactManager.cs @@ -0,0 +1,132 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class MonsterTeamGainsItemsArtifactManager +{ + private static GameObject networkedInventoryPrefab; + + private static Inventory monsterTeamInventory; + + private static readonly Xoroshiro128Plus treasureRng = new Xoroshiro128Plus(0uL); + + private static PickupDropTable[] dropPattern; + + private static int currentItemIterator = 0; + + private static ArtifactDef myArtifact => RoR2Content.Artifacts.monsterTeamGainsItemsArtifactDef; + + [SystemInitializer(new Type[] + { + typeof(ArtifactCatalog), + typeof(ItemCatalog) + })] + private static void Init() + { + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + Run.onRunStartGlobal += OnRunStartGlobal; + Run.onRunDestroyGlobal += OnRunDestroyGlobal; + Stage.onServerStageBegin += OnServerStageBegin; + SceneDirector.onPrePopulateSceneServer += OnPrePopulateSceneServer; + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/MonsterTeamGainsItemsArtifactInventory", delegate(GameObject operationResult) + { + networkedInventoryPrefab = operationResult; + }); + PickupDropTable pickupDropTable = LegacyResourcesAPI.Load("DropTables/dtMonsterTeamTier1Item"); + PickupDropTable pickupDropTable2 = LegacyResourcesAPI.Load("DropTables/dtMonsterTeamTier2Item"); + PickupDropTable pickupDropTable3 = LegacyResourcesAPI.Load("DropTables/dtMonsterTeamTier3Item"); + dropPattern = new PickupDropTable[5] { pickupDropTable, pickupDropTable, pickupDropTable2, pickupDropTable2, pickupDropTable3 }; + } + + private static void OnRunStartGlobal(Run run) + { + if (NetworkServer.active) + { + currentItemIterator = 0; + treasureRng.ResetSeed(run.seed); + monsterTeamInventory = UnityEngine.Object.Instantiate(networkedInventoryPrefab).GetComponent(); + monsterTeamInventory.GetComponent().teamIndex = TeamIndex.Monster; + NetworkServer.Spawn(monsterTeamInventory.gameObject); + EnsureMonsterItemCountMatchesStageCount(); + } + } + + private static void OnRunDestroyGlobal(Run run) + { + treasureRng.ResetSeed(0uL); + if ((bool)monsterTeamInventory) + { + NetworkServer.Destroy(monsterTeamInventory.gameObject); + } + monsterTeamInventory = null; + } + + private static void GrantMonsterTeamItem() + { + PickupDropTable pickupDropTable = dropPattern[currentItemIterator++ % dropPattern.Length]; + if (!pickupDropTable) + { + return; + } + PickupIndex pickupIndex = pickupDropTable.GenerateDrop(treasureRng); + if (pickupIndex != PickupIndex.none) + { + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + if (pickupDef != null) + { + monsterTeamInventory.GiveItem(pickupDef.itemIndex); + } + } + } + + private static void EnsureMonsterItemCountMatchesStageCount() + { + EnsureMonsterTeamItemCount(Run.instance.stageClearCount + 1); + } + + private static void OnServerStageBegin(Stage stage) + { + EnsureMonsterItemCountMatchesStageCount(); + } + + private static void OnPrePopulateSceneServer(SceneDirector sceneDirector) + { + EnsureMonsterItemCountMatchesStageCount(); + } + + private static void EnsureMonsterTeamItemCount(int itemCount) + { + while (currentItemIterator < itemCount) + { + GrantMonsterTeamItem(); + } + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact) && NetworkServer.active) + { + SpawnCard.onSpawnedServerGlobal += OnServerCardSpawnedGlobal; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + SpawnCard.onSpawnedServerGlobal -= OnServerCardSpawnedGlobal; + } + } + + private static void OnServerCardSpawnedGlobal(SpawnCard.SpawnResult spawnResult) + { + CharacterMaster characterMaster = (spawnResult.spawnedInstance ? spawnResult.spawnedInstance.GetComponent() : null); + if ((bool)characterMaster && characterMaster.teamIndex == TeamIndex.Monster) + { + characterMaster.inventory.AddItemsFrom(monsterTeamInventory); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/SacrificeArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/SacrificeArtifactManager.cs new file mode 100644 index 0000000..69051b5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/SacrificeArtifactManager.cs @@ -0,0 +1,99 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class SacrificeArtifactManager +{ + private static PickupDropTable dropTable; + + private static readonly Xoroshiro128Plus treasureRng = new Xoroshiro128Plus(0uL); + + private static ArtifactDef myArtifact => RoR2Content.Artifacts.sacrificeArtifactDef; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + LegacyResourcesAPI.LoadAsyncCallback("DropTables/dtSacrificeArtifact", delegate(PickupDropTable operationResult) + { + dropTable = operationResult; + }); + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + Stage.onServerStageBegin += OnServerStageBegin; + } + + private static void OnServerStageBegin(Stage stage) + { + treasureRng.ResetSeed(Run.instance.treasureRng.nextUlong); + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (NetworkServer.active && !(artifactDef != myArtifact)) + { + GlobalEventManager.onCharacterDeathGlobal += OnServerCharacterDeath; + SceneDirector.onPrePopulateSceneServer += OnPrePopulateSceneServer; + SceneDirector.onGenerateInteractableCardSelection += OnGenerateInteractableCardSelection; + DirectorCardCategorySelection.calcCardWeight += CalcCardWeight; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + SceneDirector.onGenerateInteractableCardSelection -= OnGenerateInteractableCardSelection; + SceneDirector.onPrePopulateSceneServer -= OnPrePopulateSceneServer; + GlobalEventManager.onCharacterDeathGlobal -= OnServerCharacterDeath; + DirectorCardCategorySelection.calcCardWeight -= CalcCardWeight; + } + } + + private static void CalcCardWeight(DirectorCard card, ref float weight) + { + InteractableSpawnCard interactableSpawnCard = card.spawnCard as InteractableSpawnCard; + if (interactableSpawnCard != null) + { + weight *= interactableSpawnCard.weightScalarWhenSacrificeArtifactEnabled; + } + } + + private static void OnGenerateInteractableCardSelection(SceneDirector sceneDirector, DirectorCardCategorySelection dccs) + { + dccs.RemoveCardsThatFailFilter(IsNotChest); + static bool IsNotChest(DirectorCard card) + { + InteractableSpawnCard obj = card.spawnCard as InteractableSpawnCard; + if ((object)obj == null) + { + return true; + } + return !obj.skipSpawnWhenSacrificeArtifactEnabled; + } + } + + private static void OnPrePopulateSceneServer(SceneDirector sceneDirector) + { + sceneDirector.onPopulateCreditMultiplier *= 0.5f; + } + + private static void OnServerCharacterDeath(DamageReport damageReport) + { + if (!damageReport.victimMaster || (damageReport.attackerTeamIndex == damageReport.victimTeamIndex && (bool)damageReport.victimMaster.minionOwnership.ownerMaster)) + { + return; + } + float expAdjustedDropChancePercent = Util.GetExpAdjustedDropChancePercent(5f, damageReport.victim.gameObject); + Debug.LogFormat("Drop chance from {0}: {1}", damageReport.victimBody, expAdjustedDropChancePercent); + if (Util.CheckRoll(expAdjustedDropChancePercent)) + { + PickupIndex pickupIndex = dropTable.GenerateDrop(treasureRng); + if (pickupIndex != PickupIndex.none) + { + PickupDropletController.CreatePickupDroplet(pickupIndex, damageReport.victimBody.corePosition, Vector3.up * 20f); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/SwarmsArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/SwarmsArtifactManager.cs new file mode 100644 index 0000000..27165f8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/SwarmsArtifactManager.cs @@ -0,0 +1,78 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class SwarmsArtifactManager +{ + private const int swarmSpawnCount = 2; + + private static bool inSpawn; + + private static ArtifactDef myArtifact => RoR2Content.Artifacts.swarmsArtifactDef; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact) && NetworkServer.active) + { + SpawnCard.onSpawnedServerGlobal += OnSpawnCardOnSpawnedServerGlobal; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifact)) + { + SpawnCard.onSpawnedServerGlobal -= OnSpawnCardOnSpawnedServerGlobal; + } + } + + private static void OnSpawnCardOnSpawnedServerGlobal(SpawnCard.SpawnResult result) + { + if (!result.success || !(result.spawnRequest.spawnCard as CharacterSpawnCard) || result.spawnRequest.teamIndexOverride == TeamIndex.Player) + { + return; + } + CharacterMaster component = result.spawnedInstance.gameObject.GetComponent(); + if ((bool)component) + { + component.inventory.GiveItem(RoR2Content.Items.CutHp); + GameObject bodyObject = component.GetBodyObject(); + if ((bool)bodyObject) + { + DeathRewards component2 = bodyObject.GetComponent(); + if ((bool)component2) + { + component2.spawnValue = (int)Mathf.Max(1f, (float)component2.spawnValue / 2f); + component2.expReward = (uint)Mathf.Ceil((float)component2.expReward / 2f); + component2.goldReward = (uint)Mathf.Ceil((float)component2.goldReward / 2f); + } + } + } + if (inSpawn) + { + return; + } + for (int i = 1; i < 2; i++) + { + inSpawn = true; + try + { + DirectorCore.instance.TrySpawnObject(result.spawnRequest); + } + catch (Exception message) + { + Debug.LogError(message); + } + inSpawn = false; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Artifacts/TeamDeathArtifactManager.cs b/ilspy_dump/ror2_csproj/RoR2.Artifacts/TeamDeathArtifactManager.cs new file mode 100644 index 0000000..c31a500 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Artifacts/TeamDeathArtifactManager.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.ObjectModel; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Artifacts; + +public static class TeamDeathArtifactManager +{ + private static GameObject forceSpectatePrefab; + + private static bool inTeamKill; + + private static ArtifactDef myArtifactDef => RoR2Content.Artifacts.teamDeathArtifactDef; + + [SystemInitializer(new Type[] { typeof(ArtifactCatalog) })] + private static void Init() + { + RunArtifactManager.onArtifactEnabledGlobal += OnArtifactEnabled; + RunArtifactManager.onArtifactDisabledGlobal += OnArtifactDisabled; + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/ForceSpectate", delegate(GameObject operationResult) + { + forceSpectatePrefab = operationResult; + }); + } + + private static void OnArtifactEnabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifactDef)) + { + GlobalEventManager.onCharacterDeathGlobal += OnServerCharacterDeathGlobal; + } + } + + private static void OnArtifactDisabled(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) + { + if (!(artifactDef != myArtifactDef)) + { + GlobalEventManager.onCharacterDeathGlobal -= OnServerCharacterDeathGlobal; + } + } + + private static void OnServerCharacterDeathGlobal(DamageReport damageReport) + { + TeamIndex teamIndex; + NetworkUser victimNetworkUser; + if (!inTeamKill && (bool)damageReport.victimMaster && (bool)damageReport.victimMaster.playerCharacterMasterController) + { + if (damageReport.victimMaster.inventory.GetItemCount(RoR2Content.Items.ExtraLife) <= 0 && damageReport.victimMaster.inventory.GetItemCount(DLC1Content.Items.ExtraLifeVoid) <= 0 && !damageReport.victimBody.HasBuff(DLC2Content.Buffs.ExtraLifeBuff) && damageReport.victimBody.equipmentSlot.equipmentIndex != DLC2Content.Equipment.HealAndRevive.equipmentIndex) + { + GameObject gameObject = UnityEngine.Object.Instantiate(forceSpectatePrefab); + gameObject.GetComponent().Networktarget = damageReport.victimBody.gameObject; + NetworkServer.Spawn(gameObject); + teamIndex = damageReport.victimTeamIndex; + PlayerCharacterMasterController playerCharacterMasterController = damageReport.victimMaster.playerCharacterMasterController; + victimNetworkUser = (playerCharacterMasterController ? playerCharacterMasterController.networkUser : null); + RoR2Application.onNextUpdate += KillTeam; + } + } + void KillTeam() + { + inTeamKill = true; + Chat.SendBroadcastChat(new SubjectChatMessage + { + baseToken = "ARTIFACT_TEAMDEATH_DEATHMESSAGE", + subjectAsNetworkUser = victimNetworkUser + }); + ReadOnlyCollection readOnlyInstancesList = CharacterMaster.readOnlyInstancesList; + for (int num = readOnlyInstancesList.Count - 1; num >= 0; num--) + { + if (readOnlyInstancesList[num].teamIndex == teamIndex) + { + readOnlyInstancesList[num].TrueKill(); + } + } + inTeamKill = false; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/AkEventIdArg.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/AkEventIdArg.cs new file mode 100644 index 0000000..3145ce1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/AkEventIdArg.cs @@ -0,0 +1,26 @@ +namespace RoR2.Audio; + +public struct AkEventIdArg +{ + public readonly uint id; + + public static explicit operator AkEventIdArg(string eventName) + { + return new AkEventIdArg((eventName != null) ? AkSoundEngine.GetIDFromString(eventName) : 0u); + } + + public static implicit operator AkEventIdArg(uint akEventId) + { + return new AkEventIdArg(akEventId); + } + + public static implicit operator uint(AkEventIdArg akEventIdArg) + { + return akEventIdArg.id; + } + + private AkEventIdArg(uint id) + { + this.id = id; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/EntitySoundManager.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/EntitySoundManager.cs new file mode 100644 index 0000000..591c55f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/EntitySoundManager.cs @@ -0,0 +1,95 @@ +using RoR2.Networking; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Audio; + +public static class EntitySoundManager +{ + private class EntitySoundMessage : MessageBase + { + public NetworkSoundEventIndex networkSoundEventIndex; + + public NetworkIdentity networkIdentity; + + public override void Serialize(NetworkWriter writer) + { + base.Serialize(writer); + writer.WriteNetworkSoundEventIndex(networkSoundEventIndex); + writer.Write(networkIdentity); + } + + public override void Deserialize(NetworkReader reader) + { + base.Deserialize(reader); + networkSoundEventIndex = reader.ReadNetworkSoundEventIndex(); + networkIdentity = reader.ReadNetworkIdentity(); + } + + public void Clear() + { + networkSoundEventIndex = NetworkSoundEventIndex.Invalid; + networkIdentity = null; + } + } + + private static readonly EntitySoundMessage sharedMessage = new EntitySoundMessage(); + + private static readonly QosChannelIndex channel = QosChannelIndex.defaultReliable; + + private static readonly short messageType = 73; + + [NetworkMessageHandler(client = true, server = false, msgType = 73)] + private static void HandleMessage(NetworkMessage netMsg) + { + netMsg.ReadMessage(sharedMessage); + if ((bool)sharedMessage.networkIdentity) + { + EmitSoundLocal(NetworkSoundEventCatalog.GetAkIdFromNetworkSoundEventIndex(sharedMessage.networkSoundEventIndex), sharedMessage.networkIdentity.gameObject); + } + sharedMessage.Clear(); + } + + public static uint EmitSoundLocal(AkEventIdArg akEventId, GameObject gameObject) + { + if ((uint)akEventId == 0) + { + return 0u; + } + return AkSoundEngine.PostEvent(akEventId, gameObject); + } + + public static void EmitSoundServer(AkEventIdArg akEventId, GameObject gameObject) + { + NetworkSoundEventIndex networkSoundEventIndex = NetworkSoundEventCatalog.FindNetworkSoundEventIndex(akEventId); + if (networkSoundEventIndex == NetworkSoundEventIndex.Invalid) + { + Debug.LogWarningFormat("Cannot emit sound \"{0}\" on object \"{1}\": Event is not registered in NetworkSoundEventCatalog.", akEventId.id, gameObject); + } + else + { + EmitSoundServer(networkSoundEventIndex, gameObject); + } + } + + public static void EmitSoundServer(NetworkSoundEventIndex networkSoundEventIndex, GameObject gameObject) + { + NetworkIdentity component = gameObject.GetComponent(); + if (!component) + { + Debug.LogWarningFormat("Cannot emit sound \"{0}\" on object \"{1}\": Object has no NetworkIdentity.", NetworkSoundEventCatalog.GetAkIdFromNetworkSoundEventIndex(networkSoundEventIndex), gameObject); + } + else + { + EmitSoundServer(networkSoundEventIndex, component); + } + } + + public static void EmitSoundServer(NetworkSoundEventIndex networkSoundEventIndex, NetworkIdentity networkIdentity) + { + sharedMessage.networkIdentity = networkIdentity; + sharedMessage.networkSoundEventIndex = networkSoundEventIndex; + NetworkServer.SendByChannelToAll(messageType, sharedMessage, channel.intVal); + sharedMessage.Clear(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/LoopSoundDef.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/LoopSoundDef.cs new file mode 100644 index 0000000..3c2f921 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/LoopSoundDef.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace RoR2.Audio; + +[CreateAssetMenu(menuName = "RoR2/LoopSoundDef")] +public class LoopSoundDef : ScriptableObject +{ + public string startSoundName; + + public string stopSoundName; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/LoopSoundManager.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/LoopSoundManager.cs new file mode 100644 index 0000000..acd85e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/LoopSoundManager.cs @@ -0,0 +1,136 @@ +using HG; +using UnityEngine; + +namespace RoR2.Audio; + +public static class LoopSoundManager +{ + public struct SoundLoopPtr + { + public readonly ValueHeap.Ptr ptr; + + public bool isValid => soundLoopHeap.PtrIsValid(in ptr); + + public SoundLoopPtr(ValueHeap.Ptr ptr) + { + this.ptr = ptr; + } + + public SoundLoopNode GetValue() + { + return soundLoopHeap.GetValue(in ptr); + } + + public void SetValue(in SoundLoopNode value) + { + soundLoopHeap.SetValue(in ptr, in value); + } + + public ref SoundLoopNode GetRef() + { + return ref soundLoopHeap.GetRef(ptr); + } + + public void SetRtpc(string rtpcName, float value) + { + AkSoundEngine.SetRTPCValueByPlayingID(rtpcName, value, GetRef().akId); + } + } + + public class SoundLoopHelper : MonoBehaviour + { + public SoundLoopPtr first { get; set; } + + public SoundLoopPtr last { get; set; } + + public GameObject cachedGameObject { get; set; } + + private void OnDestroy() + { + while (first.isValid) + { + StopSoundLoopLocal(first); + } + } + } + + public struct SoundLoopNode + { + public SoundLoopHelper owner; + + public LoopSoundDef loopSoundDef; + + public uint akId; + + public SoundLoopPtr next; + + public SoundLoopPtr previous; + } + + private static readonly ValueHeap soundLoopHeap = new ValueHeap(128u); + + public static SoundLoopPtr PlaySoundLoopLocal(GameObject gameObject, LoopSoundDef loopSoundDef) + { + gameObject.GetComponent(); + SoundLoopHelper soundLoopHelper = gameObject.GetComponent(); + if (!soundLoopHelper) + { + soundLoopHelper = gameObject.AddComponent(); + soundLoopHelper.cachedGameObject = soundLoopHelper.gameObject; + } + SoundLoopPtr soundLoopPtr = new SoundLoopPtr(soundLoopHeap.Alloc()); + SoundLoopPtr last = soundLoopHelper.last; + ref SoundLoopNode @ref = ref soundLoopPtr.GetRef(); + @ref.owner = soundLoopHelper; + @ref.loopSoundDef = loopSoundDef; + if (soundLoopHelper.last.isValid) + { + @ref.previous = last; + last.GetRef().next = soundLoopPtr; + } + else + { + soundLoopHelper.first = soundLoopPtr; + } + soundLoopHelper.last = soundLoopPtr; + @ref.akId = AkSoundEngine.PostEvent(loopSoundDef.startSoundName, gameObject); + return soundLoopPtr; + } + + public static SoundLoopPtr PlaySoundLoopLocalRtpc(GameObject gameObject, LoopSoundDef loopSoundDef, string rtpcName, float rtpcValue) + { + SoundLoopPtr result = PlaySoundLoopLocal(gameObject, loopSoundDef); + ref SoundLoopNode @ref = ref result.GetRef(); + if (@ref.akId != 0) + { + AkSoundEngine.SetRTPCValueByPlayingID(rtpcName, rtpcValue, @ref.akId); + } + return result; + } + + public static void StopSoundLoopLocal(SoundLoopPtr ptr) + { + if (ptr.isValid) + { + ref SoundLoopNode @ref = ref ptr.GetRef(); + AkSoundEngine.PostEvent(@ref.loopSoundDef.stopSoundName, @ref.owner.cachedGameObject); + if (@ref.previous.isValid) + { + @ref.previous.GetRef().next = @ref.next; + } + else + { + @ref.owner.first = @ref.next; + } + if (@ref.next.isValid) + { + @ref.next.GetRef().previous = @ref.previous; + } + else + { + @ref.owner.last = @ref.previous; + } + soundLoopHeap.Free(in ptr.ptr); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/NetworkSoundEventCatalog.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/NetworkSoundEventCatalog.cs new file mode 100644 index 0000000..912134a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/NetworkSoundEventCatalog.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using HG; +using RoR2.ContentManagement; +using RoR2.Modding; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Audio; + +public static class NetworkSoundEventCatalog +{ + private static NetworkSoundEventDef[] entries = Array.Empty(); + + private static readonly Dictionary eventNameToIndexTable = new Dictionary(); + + private static readonly Dictionary eventIdToIndexTable = new Dictionary(); + + [Obsolete("Use IContentPackProvider instead.")] + public static event Action> getSoundEventDefs + { + add + { + LegacyModContentPackProvider.instance.HandleLegacyGetAdditionalEntries("RoR2.Audio.NetworkSoundCatalog.getSoundEventDefs", value, LegacyModContentPackProvider.instance.registrationContentPack.networkSoundEventDefs); + } + remove + { + } + } + + [SystemInitializer(new Type[] { })] + private static void Init() + { + SetNetworkSoundEvents(ContentManager.networkSoundEventDefs); + } + + public static void SetNetworkSoundEvents(NetworkSoundEventDef[] newEntries) + { + eventNameToIndexTable.Clear(); + eventIdToIndexTable.Clear(); + ArrayUtils.CloneTo(newEntries, ref entries); + Array.Sort(entries, (NetworkSoundEventDef a, NetworkSoundEventDef b) => string.CompareOrdinal(a.name, b.name)); + for (int i = 0; i < entries.Length; i++) + { + NetworkSoundEventDef networkSoundEventDef = entries[i]; + networkSoundEventDef.index = (NetworkSoundEventIndex)i; + networkSoundEventDef.akId = AkSoundEngine.GetIDFromString(networkSoundEventDef.eventName); + if (networkSoundEventDef.akId == 0) + { + Debug.LogErrorFormat("Error during network sound registration: Wwise event \"{0}\" does not exist.", networkSoundEventDef.eventName); + } + } + for (int j = 0; j < entries.Length; j++) + { + NetworkSoundEventDef networkSoundEventDef2 = entries[j]; + eventNameToIndexTable[networkSoundEventDef2.eventName] = networkSoundEventDef2.index; + eventIdToIndexTable[networkSoundEventDef2.akId] = networkSoundEventDef2.index; + } + } + + public static NetworkSoundEventIndex FindNetworkSoundEventIndex(string eventName) + { + if (eventNameToIndexTable.TryGetValue(eventName, out var value)) + { + return value; + } + return NetworkSoundEventIndex.Invalid; + } + + public static NetworkSoundEventIndex FindNetworkSoundEventIndex(uint akEventId) + { + if (eventIdToIndexTable.TryGetValue(akEventId, out var value)) + { + return value; + } + return NetworkSoundEventIndex.Invalid; + } + + public static uint GetAkIdFromNetworkSoundEventIndex(NetworkSoundEventIndex eventIndex) + { + if (eventIndex == NetworkSoundEventIndex.Invalid) + { + return 0u; + } + return entries[(int)eventIndex].akId; + } + + public static void WriteNetworkSoundEventIndex(this NetworkWriter writer, NetworkSoundEventIndex networkSoundEventIndex) + { + writer.WritePackedUInt32((uint)(networkSoundEventIndex + 1)); + } + + public static NetworkSoundEventIndex ReadNetworkSoundEventIndex(this NetworkReader reader) + { + return (NetworkSoundEventIndex)(reader.ReadPackedUInt32() - 1); + } + + public static string GetEventNameFromId(uint akEventId) + { + if (eventIdToIndexTable.TryGetValue(akEventId, out var value)) + { + return entries[(int)value].eventName; + } + return null; + } + + public static string GetEventNameFromNetworkIndex(NetworkSoundEventIndex networkSoundEventIndex) + { + return ArrayUtils.GetSafe(entries, (int)networkSoundEventIndex)?.eventName; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/NetworkSoundEventIndex.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/NetworkSoundEventIndex.cs new file mode 100644 index 0000000..7e0795a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/NetworkSoundEventIndex.cs @@ -0,0 +1,6 @@ +namespace RoR2.Audio; + +public enum NetworkSoundEventIndex +{ + Invalid = -1 +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Audio/PointSoundManager.cs b/ilspy_dump/ror2_csproj/RoR2.Audio/PointSoundManager.cs new file mode 100644 index 0000000..e29bb17 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Audio/PointSoundManager.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using RoR2.ConVar; +using RoR2.Networking; +using UnityEngine; +using UnityEngine.AddressableAssets; +using UnityEngine.Networking; +using UnityEngine.ResourceManagement.AsyncOperations; +using UnityEngine.SceneManagement; + +namespace RoR2.Audio; + +public static class PointSoundManager +{ + private class NetworkSoundEventMessage : MessageBase + { + public NetworkSoundEventIndex soundEventIndex; + + public Vector3 position; + + public override void Serialize(NetworkWriter writer) + { + base.Serialize(writer); + writer.WriteNetworkSoundEventIndex(soundEventIndex); + writer.Write(position); + } + + public override void Deserialize(NetworkReader reader) + { + base.Deserialize(reader); + soundEventIndex = reader.ReadNetworkSoundEventIndex(); + position = reader.ReadVector3(); + } + } + + private struct TimeoutInfo + { + public readonly AkGameObj emitter; + + public readonly float startTime; + + public TimeoutInfo(AkGameObj emitter, float startTime) + { + this.emitter = emitter; + this.startTime = startTime; + } + } + + private static readonly Stack emitterPool = new Stack(); + + private static GameObject emitterObjectPrefab; + + private const uint EMPTY_AK_EVENT_SOUND = 2166136261u; + + private static readonly NetworkSoundEventMessage sharedMessage = new NetworkSoundEventMessage(); + + private static readonly QosChannelIndex channel = QosChannelIndex.effects; + + private const short messageType = 72; + + private static readonly FloatConVar cvPointSoundManagerTimeout = new FloatConVar("pointsoundmanager_timeout", ConVarFlags.None, "4.5", "Timeout value in seconds to use for sound emitters dispatched by PointSoundManager. -1 for end-of-playback callbacks instead, which we suspect may have thread-safety issues."); + + private static readonly Queue timeouts = new Queue(); + + [InitDuringStartup] + private static void InitSoundEmitter() + { + RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate + { + LoadEmitterPrefab(); + }); + } + + private static void LoadEmitterPrefab() + { + AsyncOperationHandle asyncOperationHandle = Addressables.LoadAssetAsync("29b2b6ef68391f74e91693f36016b301"); + asyncOperationHandle.Completed += delegate(AsyncOperationHandle obj) + { + SetEmitterPrefab(obj.Result); + }; + } + + private static void SetEmitterPrefab(GameObject emitterPrefab) + { + emitterObjectPrefab = emitterPrefab; + } + + private static AkGameObj RequestEmitter() + { + if (emitterPool.Count > 0) + { + return emitterPool.Pop(); + } + if ((bool)emitterObjectPrefab) + { + return UnityEngine.Object.Instantiate(emitterObjectPrefab).GetComponent(); + } + LoadEmitterPrefab(); + GameObject gameObject = new GameObject("SoundEmitter"); + gameObject.AddComponent().isKinematic = true; + return gameObject.AddComponent(); + } + + private static void FreeEmitter(AkGameObj emitter) + { + if ((bool)emitter) + { + emitterPool.Push(emitter); + } + } + + public static uint EmitSoundLocal(AkEventIdArg akEventId, Vector3 position) + { + if (WwiseIntegrationManager.noAudio || akEventId.id == 0 || akEventId.id == 2166136261u) + { + return 0u; + } + AkGameObj akGameObj = RequestEmitter(); + akGameObj.transform.position = position; + akGameObj.SetPosition(); + uint result; + if (cvPointSoundManagerTimeout.value < 0f) + { + result = AkSoundEngine.PostEvent(akEventId, akGameObj.gameObject, 1u, Callback, akGameObj); + } + else + { + result = AkSoundEngine.PostEvent(akEventId, akGameObj.gameObject); + timeouts.Enqueue(new TimeoutInfo(akGameObj, Time.unscaledTime)); + } + return result; + } + + private static void Callback(object cookie, AkCallbackType in_type, AkCallbackInfo in_info) + { + if (in_type == AkCallbackType.AK_EndOfEvent) + { + FreeEmitter((AkGameObj)cookie); + } + } + + [RuntimeInitializeOnLoadMethod] + private static void Init() + { + SceneManager.sceneUnloaded += OnSceneUnloaded; + RoR2Application.onUpdate += StaticUpdate; + } + + private static void StaticUpdate() + { + ProcessTimeoutQueue(); + } + + private static void OnSceneUnloaded(Scene scene) + { + ClearEmitterPool(); + } + + private static void ClearEmitterPool() + { + foreach (AkGameObj item in emitterPool) + { + if ((bool)item) + { + UnityEngine.Object.Destroy(item.gameObject); + } + } + emitterPool.Clear(); + } + + public static void EmitSoundServer(NetworkSoundEventIndex networkSoundEventIndex, Vector3 position) + { + sharedMessage.soundEventIndex = networkSoundEventIndex; + sharedMessage.position = position; + NetworkServer.SendByChannelToAll(72, sharedMessage, channel.intVal); + } + + [NetworkMessageHandler(client = true, server = false, msgType = 72)] + private static void HandleMessage(NetworkMessage netMsg) + { + netMsg.ReadMessage(sharedMessage); + EmitSoundLocal(NetworkSoundEventCatalog.GetAkIdFromNetworkSoundEventIndex(sharedMessage.soundEventIndex), sharedMessage.position); + } + + private static void ProcessTimeoutQueue() + { + float num = Time.unscaledTime - cvPointSoundManagerTimeout.value; + while (timeouts.Count > 0) + { + TimeoutInfo timeoutInfo = timeouts.Peek(); + if (!(num <= timeoutInfo.startTime)) + { + timeouts.Dequeue(); + FreeEmitter(timeoutInfo.emitter); + continue; + } + break; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModeBase.cs b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModeBase.cs new file mode 100644 index 0000000..79e0151 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModeBase.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections.Generic; +using HG; +using Rewired; +using RoR2.Networking; +using RoR2.UI; +using UnityEngine; + +namespace RoR2.CameraModes; + +public abstract class CameraModeBase +{ + public struct CameraInfo + { + public CameraRigController cameraRigController; + + public Camera sceneCam; + + public ICameraStateProvider overrideCam; + + public CameraState previousCameraState; + + public float baseFov; + } + + public struct TargetInfo + { + public GameObject target; + + public CharacterBody body; + + public InputBankTest inputBank; + + public CameraTargetParams targetParams; + + public TeamIndex teamIndex; + + public bool isSprinting; + + public bool skillsAreDisabled; + + public bool isViewerControlled; + + public CharacterMaster master; + + public NetworkUser networkUser; + + public NetworkedViewAngles networkedViewAngles; + } + + public struct ViewerInfo + { + public LocalUser localUser; + + public UserProfile userProfile; + + public Player inputPlayer; + + public MPEventSystem eventSystem; + + public bool hasCursor; + + public bool isUIFocused; + } + + public struct CameraModeContext + { + public CameraInfo cameraInfo; + + public TargetInfo targetInfo; + + public ViewerInfo viewerInfo; + } + + public struct UpdateArgs + { + public CameraInfo cameraInfo; + + public TargetInfo targetInfo; + } + + public struct UpdateResult + { + public GameObject firstPersonTarget; + + public CameraState cameraState; + + public bool showSprintParticles; + + public bool showDisabledSkillsParticles; + + public Vector3 crosshairWorldPosition; + } + + public struct CollectLookInputResult + { + public Vector2 lookInput; + } + + public struct ApplyLookInputArgs + { + public Vector2 lookInput; + } + + public struct OnTargetChangedArgs + { + public GameObject oldTarget; + + public GameObject newTarget; + } + + private Dictionary, object> camToRawInstanceData = new Dictionary, object>(); + + public void OnInstall(CameraRigController cameraRigController) + { + object obj = CreateInstanceData(cameraRigController); + camToRawInstanceData.Add(cameraRigController, obj); + try + { + OnInstallInternal(obj, cameraRigController); + } + catch (Exception message) + { + Debug.LogError(message); + } + if ((object)cameraRigController.target != null) + { + OnTargetChanged(cameraRigController, new OnTargetChangedArgs + { + oldTarget = null, + newTarget = cameraRigController.target + }); + } + } + + protected virtual void OnInstallInternal(object rawInstancedata, CameraRigController cameraRigController) + { + } + + public void OnUninstall(CameraRigController cameraRigController) + { + if ((object)cameraRigController.target != null) + { + OnTargetChanged(cameraRigController, new OnTargetChangedArgs + { + oldTarget = cameraRigController.target, + newTarget = null + }); + } + try + { + OnUninstallInternal(camToRawInstanceData[cameraRigController], cameraRigController); + } + catch (Exception message) + { + Debug.LogError(message); + } + camToRawInstanceData.Remove(cameraRigController); + } + + protected virtual void OnUninstallInternal(object rawInstanceData, CameraRigController cameraRigController) + { + } + + protected abstract object CreateInstanceData(CameraRigController cameraRigController); + + public abstract bool IsSpectating(CameraRigController cameraRigController); + + public void Update(in CameraModeContext context, out UpdateResult result) + { + if ((bool)context.cameraInfo.cameraRigController) + { + object rawInstanceData = camToRawInstanceData[context.cameraInfo.cameraRigController]; + UpdateInternal(rawInstanceData, in context, out result); + } + else + { + result = default(UpdateResult); + } + } + + protected abstract void UpdateInternal(object rawInstanceData, in CameraModeContext context, out UpdateResult result); + + public void CollectLookInput(in CameraModeContext context, out CollectLookInputResult result) + { + object rawInstanceData = camToRawInstanceData[context.cameraInfo.cameraRigController]; + CollectLookInputInternal(rawInstanceData, in context, out result); + } + + protected abstract void CollectLookInputInternal(object rawInstanceData, in CameraModeContext context, out CollectLookInputResult result); + + public void ApplyLookInput(in CameraModeContext context, in ApplyLookInputArgs args) + { + object rawInstanceData = camToRawInstanceData[context.cameraInfo.cameraRigController]; + ApplyLookInputInternal(rawInstanceData, in context, in args); + } + + protected abstract void ApplyLookInputInternal(object rawInstanceData, in CameraModeContext context, in ApplyLookInputArgs input); + + public void OnTargetChanged(CameraRigController cameraRigController, OnTargetChangedArgs args) + { + object rawInstanceData = camToRawInstanceData[cameraRigController]; + OnTargetChangedInternal(rawInstanceData, cameraRigController, in args); + } + + protected abstract void OnTargetChangedInternal(object rawInstanceData, CameraRigController cameraRigController, in OnTargetChangedArgs args); + + public void MatchState(in CameraModeContext context, in CameraState cameraStateToMatch) + { + object rawInstanceData = camToRawInstanceData[context.cameraInfo.cameraRigController]; + MatchStateInternal(rawInstanceData, in context, in cameraStateToMatch); + } + + protected abstract void MatchStateInternal(object rawInstanceData, in CameraModeContext context, in CameraState cameraStateToMatch); + + public object DebugGetInstanceData(CameraRigController cameraRigController) + { + camToRawInstanceData.TryGetValue(cameraRigController, out var value); + return value; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModeNone.cs b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModeNone.cs new file mode 100644 index 0000000..bf5dfab --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModeNone.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +namespace RoR2.CameraModes; + +public class CameraModeNone : CameraModeBase +{ + public static readonly CameraModeNone instance; + + public override bool IsSpectating(CameraRigController cameraRigController) + { + return true; + } + + protected override void ApplyLookInputInternal(object rawInstanceData, in CameraModeContext context, in ApplyLookInputArgs input) + { + } + + protected override void CollectLookInputInternal(object rawInstanceData, in CameraModeContext context, out CollectLookInputResult result) + { + result.lookInput = Vector2.zero; + } + + protected override object CreateInstanceData(CameraRigController cameraRigController) + { + return null; + } + + protected override void MatchStateInternal(object rawInstanceData, in CameraModeContext context, in CameraState cameraStateToMatch) + { + } + + protected override void OnTargetChangedInternal(object rawInstanceData, CameraRigController cameraRigController, in OnTargetChangedArgs args) + { + } + + protected override void UpdateInternal(object rawInstanceData, in CameraModeContext context, out UpdateResult result) + { + result.cameraState = context.cameraInfo.previousCameraState; + result.firstPersonTarget = null; + result.showSprintParticles = false; + result.showDisabledSkillsParticles = false; + result.crosshairWorldPosition = result.cameraState.position; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModePlayer2D.cs b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModePlayer2D.cs new file mode 100644 index 0000000..a73f29b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModePlayer2D.cs @@ -0,0 +1,72 @@ +using UnityEngine; + +namespace RoR2.CameraModes; + +public class CameraModePlayer2D : CameraModeBase +{ + private class InstanceData + { + public float facing = 1f; + } + + public static readonly CameraModePlayer2D instance = new CameraModePlayer2D(); + + public override bool IsSpectating(CameraRigController cameraRigController) + { + return false; + } + + protected override void ApplyLookInputInternal(object rawInstanceData, in CameraModeContext context, in ApplyLookInputArgs input) + { + } + + protected override void CollectLookInputInternal(object rawInstanceData, in CameraModeContext context, out CollectLookInputResult result) + { + result.lookInput = Vector2.zero; + } + + protected override object CreateInstanceData(CameraRigController cameraRigController) + { + return new InstanceData(); + } + + protected override void MatchStateInternal(object rawInstanceData, in CameraModeContext context, in CameraState cameraStateToMatch) + { + } + + protected override void OnTargetChangedInternal(object rawInstanceData, CameraRigController cameraRigController, in OnTargetChangedArgs args) + { + } + + protected override void UpdateInternal(object rawInstanceData, in CameraModeContext context, out UpdateResult result) + { + InstanceData instanceData = (InstanceData)rawInstanceData; + result.cameraState = context.cameraInfo.previousCameraState; + result.firstPersonTarget = null; + result.showSprintParticles = false; + result.showDisabledSkillsParticles = false; + result.crosshairWorldPosition = result.cameraState.position; + if (!context.targetInfo.target) + { + return; + } + Quaternion identity = Quaternion.identity; + Vector3 vector = identity * Quaternion.Euler(0f, 90f, 0f) * Vector3.forward; + Quaternion quaternion = ((!context.targetInfo.body || !context.targetInfo.body.characterDirection) ? context.targetInfo.target.transform.rotation : Quaternion.Euler(0f, context.targetInfo.body.characterDirection.yaw, 0f)); + Vector3 vector2 = context.targetInfo.target.transform.position; + if ((bool)context.targetInfo.inputBank) + { + float num = Vector3.Dot(vector, context.targetInfo.inputBank.moveVector); + if (num != 0f) + { + instanceData.facing = num; + } + vector2 = context.targetInfo.inputBank.aimOrigin; + } + _ = quaternion * Quaternion.Euler(0f, 90f, 0f); + result.cameraState.rotation = identity; + result.cameraState.position = context.targetInfo.target.transform.position + new Vector3(0f, 10f, 0f) + identity * Vector3.forward * -30f; + result.cameraState.fov = 60f; + result.crosshairWorldPosition = vector2 + vector * instanceData.facing * 30f; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModePlayerBasic.cs b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModePlayerBasic.cs new file mode 100644 index 0000000..f3a5a0a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CameraModes/CameraModePlayerBasic.cs @@ -0,0 +1,506 @@ +using Rewired; +using UnityEngine; + +namespace RoR2.CameraModes; + +public class CameraModePlayerBasic : CameraModeBase +{ + protected class InstanceData + { + public float currentCameraDistance; + + public float cameraDistanceVelocity; + + public float stickAimPreviousAcceleratedMagnitude; + + public float minPitch; + + public float maxPitch; + + public PitchYawPair pitchYaw; + + public CameraRigController.AimAssistInfo lastAimAssist; + + public CameraRigController.AimAssistInfo aimAssist; + + public HurtBox lastCrosshairHurtBox; + + public bool hasEverHadTarget; + + public float neutralFov; + + public float neutralFovVelocity; + + public void SetPitchYawFromLookVector(Vector3 lookVector) + { + Vector3 vector = lookVector; + float x = Mathf.Sqrt(vector.x * vector.x + vector.z * vector.z); + pitchYaw.pitch = Mathf.Atan2(0f - vector.y, x) * 57.29578f; + pitchYaw.yaw = Mathf.Repeat(Mathf.Atan2(vector.x, vector.z) * 57.29578f, 360f); + } + } + + public SurvivorIndex targetSurvivorClass; + + private bool skipFirst; + + public bool isSpectatorMode; + + public Vector3 prevGyroAngle; + + public static CameraModePlayerBasic playerBasic = new CameraModePlayerBasic + { + isSpectatorMode = false + }; + + public static CameraModePlayerBasic spectator = new CameraModePlayerBasic + { + isSpectatorMode = true + }; + + protected override object CreateInstanceData(CameraRigController cameraRigController) + { + return new InstanceData(); + } + + protected override void OnInstallInternal(object rawInstancedata, CameraRigController cameraRigController) + { + base.OnInstallInternal(rawInstancedata, cameraRigController); + ((InstanceData)rawInstancedata).neutralFov = cameraRigController.baseFov; + } + + public override bool IsSpectating(CameraRigController cameraRigController) + { + return isSpectatorMode; + } + + protected override void UpdateInternal(object rawInstanceData, in CameraModeContext context, out UpdateResult result) + { + InstanceData instanceData = (InstanceData)rawInstanceData; + CameraRigController cameraRigController = context.cameraInfo.cameraRigController; + CameraTargetParams targetParams = context.targetInfo.targetParams; + float fov = context.cameraInfo.baseFov; + Quaternion quaternion = context.cameraInfo.previousCameraState.rotation; + Vector3 position = context.cameraInfo.previousCameraState.position; + GameObject firstPersonTarget = null; + float num = cameraRigController.baseFov; + if (context.targetInfo.isSprinting) + { + num *= 1.3f; + } + instanceData.neutralFov = Mathf.SmoothDamp(instanceData.neutralFov, num, ref instanceData.neutralFovVelocity, 0.2f, float.PositiveInfinity, Time.deltaTime); + CharacterCameraParamsData dest = CharacterCameraParamsData.basic; + dest.fov = instanceData.neutralFov; + Vector2 vector = Vector2.zero; + if ((bool)targetParams) + { + CharacterCameraParamsData.Blend(in targetParams.currentCameraParamsData, ref dest, 1f); + fov = dest.fov.value; + vector = targetParams.recoil; + } + if (dest.isFirstPerson.value) + { + firstPersonTarget = context.targetInfo.target; + } + instanceData.minPitch = dest.minPitch.value; + instanceData.maxPitch = dest.maxPitch.value; + float pitch = instanceData.pitchYaw.pitch; + float yaw = instanceData.pitchYaw.yaw; + pitch += vector.y; + yaw += vector.x; + pitch = Mathf.Clamp(pitch, instanceData.minPitch, instanceData.maxPitch); + yaw = Mathf.Repeat(yaw, 360f); + Vector3 targetPivotPosition = CalculateTargetPivotPosition(in context); + if ((bool)context.targetInfo.target) + { + quaternion = Quaternion.Euler(pitch, yaw, 0f); + Vector3 direction = targetPivotPosition + quaternion * dest.idealLocalCameraPos.value - targetPivotPosition; + float magnitude = direction.magnitude; + float num2 = (1f + pitch / -90f) * 0.5f; + magnitude *= Mathf.Sqrt(1f - num2); + if (magnitude < 0.25f) + { + magnitude = 0.25f; + } + Ray ray = new Ray(targetPivotPosition, direction); + float num3 = cameraRigController.Raycast(new Ray(targetPivotPosition, direction), magnitude, dest.wallCushion.value - 0.01f); + Debug.DrawRay(ray.origin, ray.direction * magnitude, Color.yellow, Time.deltaTime); + Debug.DrawRay(ray.origin, ray.direction * num3, Color.red, Time.deltaTime); + if (instanceData.currentCameraDistance >= num3) + { + instanceData.currentCameraDistance = num3; + instanceData.cameraDistanceVelocity = 0f; + } + else + { + instanceData.currentCameraDistance = Mathf.SmoothDamp(instanceData.currentCameraDistance, num3, ref instanceData.cameraDistanceVelocity, 0.5f); + } + position = targetPivotPosition + direction.normalized * instanceData.currentCameraDistance; + } + result.cameraState.position = position; + result.cameraState.rotation = quaternion; + result.cameraState.fov = fov; + result.showSprintParticles = context.targetInfo.isSprinting; + result.showDisabledSkillsParticles = context.targetInfo.skillsAreDisabled; + result.firstPersonTarget = firstPersonTarget; + UpdateCrosshair(rawInstanceData, in context, in result.cameraState, in targetPivotPosition, out result.crosshairWorldPosition); + } + + protected override void CollectLookInputInternal(object rawInstanceData, in CameraModeContext context, out CollectLookInputResult output) + { + InstanceData instanceData = (InstanceData)rawInstanceData; + ref readonly CameraInfo cameraInfo = ref context.cameraInfo; + ref readonly ViewerInfo viewerInfo = ref context.viewerInfo; + ref readonly TargetInfo targetInfo = ref context.targetInfo; + bool hasCursor = viewerInfo.hasCursor; + Player inputPlayer = viewerInfo.inputPlayer; + UserProfile userProfile = viewerInfo.userProfile; + ICameraStateProvider overrideCam = cameraInfo.overrideCam; + output.lookInput = Vector3.zero; + if (!hasCursor && viewerInfo.inputPlayer != null && userProfile != null && !viewerInfo.isUIFocused && (!(Object)overrideCam || overrideCam.IsUserLookAllowed(cameraInfo.cameraRigController))) + { + Vector2 vector = new Vector2(inputPlayer.GetAxisRaw(2), inputPlayer.GetAxisRaw(3)); + Vector2 aimStickVector = new Vector2(inputPlayer.GetAxisRaw(16), inputPlayer.GetAxisRaw(17)); + ConditionalNegate(ref vector.x, userProfile.mouseLookInvertX); + ConditionalNegate(ref vector.y, userProfile.mouseLookInvertY); + ConditionalNegate(ref aimStickVector.x, userProfile.stickLookInvertX); + ConditionalNegate(ref aimStickVector.y, userProfile.stickLookInvertY); + PerformStickPostProcessing(instanceData, in context, ref aimStickVector); + float mouseLookSensitivity = userProfile.mouseLookSensitivity; + float num = userProfile.stickLookSensitivity * CameraRigController.aimStickGlobalScale.value * 45f; + Vector2 vector2 = new Vector2(userProfile.mouseLookScaleX, userProfile.mouseLookScaleY); + Vector2 vector3 = new Vector2(userProfile.stickLookScaleX, userProfile.stickLookScaleY); + vector *= vector2 * mouseLookSensitivity; + aimStickVector *= vector3 * num; + PerformAimAssist(in context, ref aimStickVector); + aimStickVector *= Time.deltaTime; + output.lookInput = vector + aimStickVector; + if (userProfile.gyroEnabled) + { + Vector3 gyroAimDeltaVector = PlatformSystems.platformManager.GetGyroAimDeltaVector(); + bool flag = false; + flag = ((targetSurvivorClass == RoR2Content.Survivors.Huntress.survivorIndex) ? userProfile.gyroDisabledDuringSprint_Huntress : ((targetSurvivorClass != RoR2Content.Survivors.Loader.survivorIndex && targetSurvivorClass != RoR2Content.Survivors.Merc.survivorIndex && targetSurvivorClass != RoR2Content.Survivors.Croco.survivorIndex) ? userProfile.gyroDisabledDuringSprint : userProfile.gyroDisabledDuringSprint_Melee)); + if (!context.targetInfo.isSprinting || !flag) + { + ConditionalNegate(ref gyroAimDeltaVector.x, userProfile.gyroLookInvertY); + ConditionalNegate(ref gyroAimDeltaVector.y, userProfile.gyroLookInvertX); + if (skipFirst) + { + output.lookInput += new Vector2((0f - gyroAimDeltaVector.y) * userProfile.gyroLookSensitivity * userProfile.gyroLookScaleX * 1250f, gyroAimDeltaVector.x * userProfile.gyroLookSensitivity * userProfile.gyroLookScaleY * 1250f); + } + else + { + skipFirst = true; + } + } + } + } + output.lookInput *= cameraInfo.previousCameraState.fov / cameraInfo.baseFov; + if (targetInfo.isSprinting && CameraRigController.enableSprintSensitivitySlowdown.value) + { + output.lookInput *= 0.5f; + } + static void ConditionalNegate(ref float value, bool condition) + { + value = (condition ? (0f - value) : value); + } + } + + private void PerformStickPostProcessing(InstanceData instanceData, in CameraModeContext context, ref Vector2 aimStickVector) + { + float magnitude = aimStickVector.magnitude; + float num = magnitude; + _ = Vector2.zero; + _ = Vector2.zero; + _ = Vector2.zero; + if (CameraRigController.aimStickDualZoneSmoothing.value != 0f) + { + float maxDelta = Time.deltaTime / CameraRigController.aimStickDualZoneSmoothing.value; + num = (instanceData.stickAimPreviousAcceleratedMagnitude = Mathf.Min(Mathf.MoveTowards(instanceData.stickAimPreviousAcceleratedMagnitude, magnitude, maxDelta), magnitude)); + if (magnitude == 0f) + { + _ = Vector2.zero; + } + else + { + _ = aimStickVector * (num / magnitude); + } + } + float num2 = num; + float value = CameraRigController.aimStickDualZoneSlope.value; + float num3 = ((!(num2 <= CameraRigController.aimStickDualZoneThreshold.value)) ? (1f - value) : 0f); + num = value * num2 + num3; + if (magnitude == 0f) + { + _ = Vector2.zero; + } + else + { + _ = aimStickVector * (num / magnitude); + } + num = Mathf.Pow(num, CameraRigController.aimStickExponent.value); + if (magnitude == 0f) + { + _ = Vector2.zero; + } + else + { + _ = aimStickVector * (num / magnitude); + } + if (magnitude != 0f) + { + aimStickVector *= num / magnitude; + } + } + + private void PerformAimAssist(in CameraModeContext context, ref Vector2 aimStickVector) + { + ref readonly TargetInfo targetInfo = ref context.targetInfo; + ref readonly CameraInfo cameraInfo = ref context.cameraInfo; + ref readonly UserProfile userProfile = ref context.viewerInfo.userProfile; + if (!context.targetInfo.isViewerControlled || context.targetInfo.isSprinting || userProfile.inputAimAssistSensitivity == 0f) + { + return; + } + Camera sceneCam = cameraInfo.sceneCam; + if (!userProfile.aimAssistEnabled) + { + return; + } + AimAssistTarget aimAssistTarget = null; + AimAssistTarget aimAssistTarget2 = null; + float value = CameraRigController.aimStickAssistMinSize.value; + float num = value * CameraRigController.aimStickAssistMaxSize.value; + Util.Remap(userProfile.inputAimAssistSensitivity, 1f, 10f, 0.4f, 0.15f); + float value2 = CameraRigController.aimStickAssistMinSlowdownScale.value; + float num2 = 0f; + float num3 = 0f; + Vector2 vector = Vector2.zero; + Vector2 normalized = aimStickVector.normalized; + Vector2 vector2 = new Vector2(0.5f, 0.5f); + for (int i = 0; i < AimAssistTarget.instancesList.Count; i++) + { + AimAssistTarget aimAssistTarget3 = AimAssistTarget.instancesList[i]; + if (aimAssistTarget3.teamComponent.teamIndex == targetInfo.teamIndex) + { + continue; + } + Vector3 vA = sceneCam.WorldToViewportPoint(aimAssistTarget3.point0.position); + Vector3 vB = sceneCam.WorldToViewportPoint(aimAssistTarget3.point1.position); + float num4 = Mathf.Lerp(vA.z, vB.z, 0.5f); + if (!(num4 <= 18f)) + { + float num5 = 1f / num4; + Vector2 vector3 = (Vector2)Util.ClosestPointOnLine(vA, vB, vector2) - vector2; + float num6 = Mathf.Clamp01(Util.Remap(vector3.magnitude, value * aimAssistTarget3.assistScale * num5, num * aimAssistTarget3.assistScale * num5, 1f, 0f)); + float num7 = Mathf.Clamp01(Vector3.Dot(vector3, normalized)); + if (num6 > num2) + { + num2 = num6; + aimAssistTarget2 = aimAssistTarget3; + num3 = num7; + aimAssistTarget = aimAssistTarget3; + vector = vector3; + } + } + } + Vector2 vector4 = aimStickVector; + if ((bool)aimAssistTarget2) + { + float outMin = Util.Remap(userProfile.aimAssistSensitivity, 1f, 10f, 0.4f, 0.15f); + float num8 = Mathf.Clamp01(Util.Remap(1f - num2, 0f, 1f, outMin, value2)); + vector4 *= num8; + } + if ((bool)aimAssistTarget && num3 != 0f) + { + float maxRadiansDelta = Util.Remap(num3, 0f, 1f, CameraRigController.aimStickAssistMinDelta.value, CameraRigController.aimStickAssistMaxDelta.value); + vector4 = Vector3.RotateTowards(vector4, vector, maxRadiansDelta, 0f); + } + aimStickVector = vector4; + } + + protected override void ApplyLookInputInternal(object rawInstanceData, in CameraModeContext context, in ApplyLookInputArgs input) + { + InstanceData instanceData = (InstanceData)rawInstanceData; + ref readonly TargetInfo targetInfo = ref context.targetInfo; + if (targetInfo.isViewerControlled) + { + float minPitch = instanceData.minPitch; + float maxPitch = instanceData.maxPitch; + instanceData.pitchYaw.pitch = Mathf.Clamp(instanceData.pitchYaw.pitch - input.lookInput.y, minPitch, maxPitch); + instanceData.pitchYaw.yaw += input.lookInput.x; + if ((bool)targetInfo.networkedViewAngles && targetInfo.networkedViewAngles.hasEffectiveAuthority) + { + targetInfo.networkedViewAngles.viewAngles = instanceData.pitchYaw; + } + } + else if ((bool)targetInfo.networkedViewAngles) + { + instanceData.pitchYaw = targetInfo.networkedViewAngles.viewAngles; + } + else if ((bool)targetInfo.inputBank) + { + instanceData.SetPitchYawFromLookVector(targetInfo.inputBank.aimDirection); + } + } + + protected void UpdateCrosshair(object rawInstanceData, in CameraModeContext context, in CameraState cameraState, in Vector3 targetPivotPosition, out Vector3 crosshairWorldPosition) + { + InstanceData instanceData = (InstanceData)rawInstanceData; + instanceData.lastAimAssist = instanceData.aimAssist; + Ray crosshairRaycastRay = GetCrosshairRaycastRay(in context, Vector2.zero, targetPivotPosition, in cameraState); + bool flag = false; + instanceData.lastCrosshairHurtBox = null; + RaycastHit raycastHit = default(RaycastHit); + int num = 0; + num = HGPhysics.RaycastAll(out var hits, crosshairRaycastRay.origin, crosshairRaycastRay.direction, context.cameraInfo.cameraRigController.maxAimRaycastDistance, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore); + float num2 = float.PositiveInfinity; + int num3 = -1; + for (int i = 0; i < num; i++) + { + RaycastHit raycastHit2 = hits[i]; + HurtBox hurtBox = raycastHit2.collider.GetComponent(); + EntityLocator component = raycastHit2.collider.GetComponent(); + float distance = raycastHit2.distance; + if (distance <= 3f || num2 <= distance) + { + continue; + } + if ((bool)hurtBox) + { + if (hurtBox.teamIndex == context.targetInfo.teamIndex) + { + continue; + } + if ((bool)hurtBox.healthComponent && hurtBox.healthComponent.dontShowHealthbar) + { + hurtBox = null; + } + } + if ((bool)component) + { + VehicleSeat vehicleSeat = (component.entity ? component.entity.GetComponent() : null); + if ((bool)vehicleSeat && vehicleSeat.currentPassengerBody == context.targetInfo.body) + { + continue; + } + } + num2 = distance; + num3 = i; + instanceData.lastCrosshairHurtBox = hurtBox; + } + if (num3 != -1) + { + flag = true; + raycastHit = hits[num3]; + } + HGPhysics.ReturnResults(hits); + instanceData.aimAssist.aimAssistHurtbox = null; + if (flag) + { + crosshairWorldPosition = raycastHit.point; + float num4 = 1000f; + if (!(raycastHit.distance < num4)) + { + return; + } + HurtBox component2 = raycastHit.collider.GetComponent(); + if (!component2) + { + return; + } + HealthComponent healthComponent = component2.healthComponent; + if (!healthComponent) + { + return; + } + TeamComponent component3 = healthComponent.GetComponent(); + if ((bool)component3 && component3.teamIndex != context.targetInfo.teamIndex && component3.teamIndex != TeamIndex.None) + { + HurtBox hurtBox2 = healthComponent.body?.mainHurtBox; + if ((bool)hurtBox2) + { + instanceData.aimAssist.aimAssistHurtbox = hurtBox2; + instanceData.aimAssist.worldPosition = raycastHit.point; + instanceData.aimAssist.localPositionOnHurtbox = hurtBox2.transform.InverseTransformPoint(raycastHit.point); + } + } + } + else + { + crosshairWorldPosition = crosshairRaycastRay.GetPoint(context.cameraInfo.cameraRigController.maxAimRaycastDistance); + } + } + + private Ray GetCrosshairRaycastRay(in CameraModeContext context, Vector2 crosshairOffset, Vector3 raycastStartPlanePoint, in CameraState cameraState) + { + if (!context.cameraInfo.sceneCam) + { + return default(Ray); + } + float fov = cameraState.fov; + float num = fov * context.cameraInfo.sceneCam.aspect; + Quaternion quaternion = Quaternion.Euler(crosshairOffset.y * fov, crosshairOffset.x * num, 0f); + quaternion = cameraState.rotation * quaternion; + return new Ray(Vector3.ProjectOnPlane(cameraState.position - raycastStartPlanePoint, cameraState.rotation * Vector3.forward) + raycastStartPlanePoint, quaternion * Vector3.forward); + } + + private Vector3 CalculateTargetPivotPosition(in CameraModeContext context) + { + CameraRigController cameraRigController = context.cameraInfo.cameraRigController; + CameraTargetParams targetParams = context.targetInfo.targetParams; + Vector3 result = context.cameraInfo.previousCameraState.position; + if ((bool)targetParams) + { + Vector3 position = targetParams.transform.position; + Vector3 vector = (targetParams.cameraPivotTransform ? targetParams.cameraPivotTransform.position : position) + new Vector3(0f, targetParams.currentCameraParamsData.pivotVerticalOffset.value, 0f); + if (targetParams.dontRaycastToPivot) + { + result = vector; + } + else + { + Vector3 direction = vector - position; + float magnitude = direction.magnitude; + Ray ray = new Ray(position, direction); + float num = cameraRigController.Raycast(ray, magnitude, targetParams.currentCameraParamsData.wallCushion.value); + Debug.DrawRay(ray.origin, ray.direction * magnitude, Color.green, Time.deltaTime); + Debug.DrawRay(ray.origin, ray.direction * num, Color.red, Time.deltaTime); + result = ray.GetPoint(num); + } + } + return result; + } + + protected override void OnTargetChangedInternal(object rawInstanceData, CameraRigController cameraRigController, in OnTargetChangedArgs args) + { + InstanceData instanceData = (InstanceData)rawInstanceData; + if (instanceData.hasEverHadTarget) + { + return; + } + if ((bool)args.newTarget) + { + CharacterBody component = args.newTarget.GetComponent(); + if ((bool)component) + { + CharacterDirection characterDirection = component.characterDirection; + if ((bool)characterDirection) + { + instanceData.pitchYaw = new PitchYawPair(0f, characterDirection.yaw); + } + targetSurvivorClass = SurvivorCatalog.GetSurvivorIndexFromBodyIndex(component.bodyIndex); + } + instanceData.hasEverHadTarget = true; + } + else + { + targetSurvivorClass = SurvivorIndex.None; + } + } + + protected override void MatchStateInternal(object rawInstanceData, in CameraModeContext context, in CameraState cameraStateToMatch) + { + ((InstanceData)rawInstanceData).SetPitchYawFromLookVector(cameraStateToMatch.rotation * Vector3.forward); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterAI/AIOwnership.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/AIOwnership.cs new file mode 100644 index 0000000..b0722d6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/AIOwnership.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +namespace RoR2.CharacterAI; + +[RequireComponent(typeof(BaseAI))] +[DisallowMultipleComponent] +public class AIOwnership : MonoBehaviour +{ + public CharacterMaster ownerMaster; + + private BaseAI baseAI; + + private void Awake() + { + baseAI = GetComponent(); + } + + private void FixedUpdate() + { + if ((bool)ownerMaster) + { + baseAI.leader.gameObject = ownerMaster.GetBodyObject(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterAI/AISkillDriver.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/AISkillDriver.cs new file mode 100644 index 0000000..959c0a6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/AISkillDriver.cs @@ -0,0 +1,158 @@ +using System; +using HG; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.Serialization; + +namespace RoR2.CharacterAI; + +public class AISkillDriver : MonoBehaviour +{ + public enum TargetType + { + CurrentEnemy, + NearestFriendlyInSkillRange, + CurrentLeader, + Custom + } + + public enum AimType + { + None, + AtMoveTarget, + AtCurrentEnemy, + AtCurrentLeader, + MoveDirection + } + + public enum MovementType + { + Stop, + ChaseMoveTarget, + StrafeMovetarget, + FleeMoveTarget + } + + public enum ButtonPressType + { + Hold, + Abstain, + TapContinuous + } + + [Tooltip("The name of this skill driver for reference purposes.")] + public string customName; + + [Tooltip("The slot of the associated skill. Set to None to allow this behavior to run regardless of skill availability.")] + public SkillSlot skillSlot; + + [Tooltip("The skill that the specified slot must have for this behavior to run. Set to none to allow any skill.")] + [Header("Selection Conditions")] + public SkillDef requiredSkill; + + [Tooltip("If set, this cannot be the dominant driver while the skill is on cooldown or out of stock.")] + public bool requireSkillReady; + + [Tooltip("If set, this cannot be the dominant driver while the equipment is on cooldown or out of stock.")] + public bool requireEquipmentReady; + + [Tooltip("The minimum health fraction required of the user for this behavior.")] + public float minUserHealthFraction = float.NegativeInfinity; + + [Tooltip("The maximum health fraction required of the user for this behavior.")] + public float maxUserHealthFraction = float.PositiveInfinity; + + [Tooltip("The minimum health fraction required of the target for this behavior.")] + public float minTargetHealthFraction = float.NegativeInfinity; + + [Tooltip("The maximum health fraction required of the target for this behavior.")] + public float maxTargetHealthFraction = float.PositiveInfinity; + + [Tooltip("The minimum distance from the target required for this behavior.")] + public float minDistance; + + [Tooltip("The maximum distance from the target required for this behavior.")] + public float maxDistance = float.PositiveInfinity; + + public bool selectionRequiresTargetLoS; + + public bool selectionRequiresOnGround; + + public bool selectionRequiresAimTarget; + + [Tooltip("The maximum number of times that this skill can be selected. If the value is < 0, then there is no maximum.")] + public int maxTimesSelected = -1; + + [FormerlySerializedAs("targetType")] + [Tooltip("The type of object targeted for movement.")] + [Header("Behavior")] + public TargetType moveTargetType; + + [Tooltip("If set, this skill will not be activated unless there is LoS to the target.")] + public bool activationRequiresTargetLoS; + + [Tooltip("If set, this skill will not be activated unless there is LoS to the aim target.")] + public bool activationRequiresAimTargetLoS; + + [Tooltip("If set, this skill will not be activated unless the aim vector is pointing close to the target.")] + public bool activationRequiresAimConfirmation; + + [Tooltip("The movement type to use while this is the dominant skill driver.")] + public MovementType movementType = MovementType.ChaseMoveTarget; + + public float moveInputScale = 1f; + + [Tooltip("Where to look while this is the dominant skill driver")] + public AimType aimType = AimType.AtMoveTarget; + + [Tooltip("If set, the nodegraph will not be used to direct the local navigator while this is the dominant skill driver. Direction toward the target will be used instead.")] + public bool ignoreNodeGraph; + + [Tooltip("If true, the AI will attempt to sprint while this is the dominant skill driver.")] + public bool shouldSprint; + + public bool shouldFireEquipment; + + [ShowFieldObsolete] + [Obsolete("Use buttonPressType instead.")] + public bool shouldTapButton; + + public ButtonPressType buttonPressType; + + [Header("Transition Behavior")] + [Tooltip("If non-negative, this value will be used for the driver evaluation timer while this is the dominant skill driver.")] + public float driverUpdateTimerOverride = -1f; + + [Tooltip("If set and this is the dominant skill driver, the current enemy will be reset at the time of the next evaluation.")] + public bool resetCurrentEnemyOnNextDriverSelection; + + [Tooltip("If true, this skill driver cannot be chosen twice in a row.")] + public bool noRepeat; + + [Tooltip("The AI skill driver that will be treated as having top priority after this one.")] + public AISkillDriver nextHighPriorityOverride; + + public float minDistanceSqr => minDistance * minDistance; + + public float maxDistanceSqr => maxDistance * maxDistance; + + public int timesSelected { get; private set; } + + private void OnValidate() + { + if (shouldTapButton) + { + buttonPressType = ButtonPressType.TapContinuous; + } + } + + private void OnEnable() + { + } + + public void OnSelected() + { + int num = timesSelected + 1; + timesSelected = num; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterAI/BaseAI.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/BaseAI.cs new file mode 100644 index 0000000..a16a2c1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/BaseAI.cs @@ -0,0 +1,964 @@ +using System; +using System.Linq; +using EntityStates; +using EntityStates.AI; +using HG; +using JetBrains.Annotations; +using RoR2.Navigation; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.CharacterAI; + +[RequireComponent(typeof(CharacterMaster))] +public class BaseAI : MonoBehaviour, IManagedMonoBehaviour +{ + [Serializable] + public class Target + { + private readonly BaseAI owner; + + private bool unset = true; + + private GameObject _gameObject; + + private float losCheckTimer; + + public HurtBox bestHurtBox; + + private HurtBoxGroup hurtBoxGroup; + + private HurtBox mainHurtBox; + + private int bullseyeCount; + + private Vector3? lastKnownBullseyePosition; + + private Run.FixedTimeStamp lastKnownBullseyePositionTime = Run.FixedTimeStamp.negativeInfinity; + + public bool hasLoS; + + public GameObject gameObject + { + get + { + return _gameObject; + } + set + { + if ((object)value != _gameObject) + { + _gameObject = value; + characterBody = gameObject?.GetComponent(); + healthComponent = characterBody?.healthComponent; + hurtBoxGroup = characterBody?.hurtBoxGroup; + bullseyeCount = (hurtBoxGroup ? hurtBoxGroup.bullseyeCount : 0); + mainHurtBox = (hurtBoxGroup ? hurtBoxGroup.mainHurtBox : null); + bestHurtBox = mainHurtBox; + hasLoS = false; + unset = !_gameObject; + } + } + } + + public CharacterBody characterBody { get; private set; } + + public HealthComponent healthComponent { get; private set; } + + public Target([NotNull] BaseAI owner) + { + this.owner = owner; + } + + public void Update() + { + if ((bool)gameObject) + { + hasLoS = (bool)bestHurtBox && owner.HasLOS(bestHurtBox.transform.position); + if (bullseyeCount > 1 && !hasLoS) + { + bestHurtBox = GetBestHurtBox(out hasLoS); + } + } + } + + public bool TestLOSNow() + { + if ((bool)bestHurtBox) + { + return owner.HasLOS(bestHurtBox.transform.position); + } + return false; + } + + public bool GetBullseyePosition(out Vector3 position) + { + if ((bool)characterBody && (bool)owner.body && (characterBody.GetVisibilityLevel(owner.body) >= VisibilityLevel.Revealed || lastKnownBullseyePositionTime.timeSince >= 2f)) + { + if ((bool)bestHurtBox) + { + lastKnownBullseyePosition = bestHurtBox.transform.position; + } + else + { + lastKnownBullseyePosition = null; + } + lastKnownBullseyePositionTime = Run.FixedTimeStamp.now; + } + if (lastKnownBullseyePosition.HasValue) + { + position = lastKnownBullseyePosition.Value; + return true; + } + position = (gameObject ? gameObject.transform.position : Vector3.zero); + return false; + } + + private HurtBox GetBestHurtBox(out bool hadLoS) + { + if ((bool)owner && (bool)owner.bodyInputBank && (bool)hurtBoxGroup) + { + Vector3 aimOrigin = owner.bodyInputBank.aimOrigin; + HurtBox hurtBox = null; + float num = float.PositiveInfinity; + HurtBox[] hurtBoxes = hurtBoxGroup.hurtBoxes; + foreach (HurtBox hurtBox2 in hurtBoxes) + { + if (!hurtBox2 || !hurtBox2.transform || !hurtBox2.isBullseye) + { + continue; + } + Vector3 position = hurtBox2.transform.position; + if (CheckLoS(aimOrigin, hurtBox2.transform.position)) + { + float sqrMagnitude = (position - aimOrigin).sqrMagnitude; + if (sqrMagnitude < num) + { + num = sqrMagnitude; + hurtBox = hurtBox2; + } + } + } + if ((bool)hurtBox) + { + hadLoS = true; + return hurtBox; + } + } + hadLoS = false; + return mainHurtBox; + } + + public void Reset() + { + if (!unset) + { + _gameObject = null; + characterBody = null; + healthComponent = null; + hurtBoxGroup = null; + bullseyeCount = 0; + mainHurtBox = null; + bestHurtBox = mainHurtBox; + hasLoS = false; + unset = true; + losCheckTimer = 0f; + } + } + } + + public struct SkillDriverEvaluation + { + public AISkillDriver dominantSkillDriver; + + public Target target; + + public Target aimTarget; + + public float separationSqrMagnitude; + } + + public struct BodyInputs + { + public Vector3 desiredAimDirection; + + public Vector3 moveVector; + + public bool pressSprint; + + public bool pressJump; + + public bool pressSkill1; + + public bool pressSkill2; + + public bool pressSkill3; + + public bool pressSkill4; + + public bool pressActivateEquipment; + } + + public bool showDebugStateChanges; + + [Tooltip("If true, this character can spot enemies behind itself.")] + public bool fullVision; + + [Tooltip("If true, this AI will not be allowed to retaliate against damage received from a source on its own team.")] + public bool neverRetaliateFriendlies; + + public float enemyAttentionDuration = 5f; + + public MapNodeGroup.GraphType desiredSpawnNodeGraphType; + + [Tooltip("The state machine to run while the body exists.")] + public EntityStateMachine stateMachine; + + public SerializableEntityStateType scanState; + + public bool isHealer; + + public float enemyAttention; + + public float aimVectorDampTime = 0.2f; + + public float aimVectorMaxSpeed = 6f; + + private float aimVelocity; + + private float targetRefreshTimer; + + private const float targetRefreshInterval = 0.5f; + + public LocalNavigator localNavigator = new LocalNavigator(); + + public string selectedSkilldriverName; + + private const float maxVisionDistance = float.PositiveInfinity; + + [Tooltip("If true and this AI remains off-screen from players until its first shot, that shot will miss. The desired skill must handle this behaviour itself. If not this will do nothing")] + public bool shouldMissFirstOffScreenShot; + + private float offScreenUpdateTimer; + + private const float offScreenUpdateInterval = 0.25f; + + public static readonly NodeGraphNavigationSystem nodeGraphNavigationSystem = new NodeGraphNavigationSystem(); + + private BroadNavigationSystem _broadNavigationSystem; + + private BroadNavigationSystem.Agent _broadNavigationAgent = BroadNavigationSystem.Agent.invalid; + + public bool forceUpdateEveryFrame; + + public HurtBox debugEnemyHurtBox; + + private BullseyeSearch enemySearch = new BullseyeSearch(); + + private BullseyeSearch buddySearch = new BullseyeSearch(); + + private float skillDriverUpdateTimer; + + private const float skillDriverMinUpdateInterval = 1f / 6f; + + private const float skillDriverMaxUpdateInterval = 0.2f; + + public SkillDriverEvaluation skillDriverEvaluation; + + protected BodyInputs bodyInputs; + + public CharacterMaster master { get; protected set; } + + public CharacterBody body { get; protected set; } + + public Transform bodyTransform { get; protected set; } + + public CharacterDirection bodyCharacterDirection { get; protected set; } + + public CharacterMotor bodyCharacterMotor { get; protected set; } + + public InputBankTest bodyInputBank { get; protected set; } + + public HealthComponent bodyHealthComponent { get; protected set; } + + public SkillLocator bodySkillLocator { get; protected set; } + + public NetworkIdentity networkIdentity { get; protected set; } + + public AISkillDriver[] skillDrivers { get; protected set; } + + public bool hasAimConfirmation { get; private set; } + + public bool hasAimTarget + { + get + { + if (skillDriverEvaluation.aimTarget != null) + { + return skillDriverEvaluation.aimTarget.gameObject; + } + return false; + } + } + + private BroadNavigationSystem broadNavigationSystem + { + get + { + return _broadNavigationSystem; + } + set + { + if (_broadNavigationSystem != value) + { + _broadNavigationSystem?.ReturnAgent(ref _broadNavigationAgent); + _broadNavigationSystem = value; + _broadNavigationSystem?.RequestAgent(ref _broadNavigationAgent); + } + } + } + + public BroadNavigationSystem.Agent broadNavigationAgent => _broadNavigationAgent; + + public bool AlwaysUpdate => forceUpdateEveryFrame; + + public Target currentEnemy { get; private set; } + + public Target leader { get; private set; } + + private Target buddy { get; set; } + + public Target customTarget { get; private set; } + + public event Action onBodyDiscovered; + + public event Action onBodyLost; + + [ContextMenu("Toggle broad navigation debug drawing")] + private void ToggleBroadNavigationDebugDraw() + { + if (broadNavigationSystem is NodeGraphNavigationSystem) + { + NodeGraphNavigationSystem.Agent agent = (NodeGraphNavigationSystem.Agent)broadNavigationAgent; + agent.drawPath = !agent.drawPath; + } + } + + public void SetBroadNavigationDebugDrawEnabled(bool newBroadNavigationDebugDrawEnabled) + { + if (broadNavigationSystem is NodeGraphNavigationSystem) + { + NodeGraphNavigationSystem.Agent agent = (NodeGraphNavigationSystem.Agent)broadNavigationAgent; + agent.drawPath = newBroadNavigationDebugDrawEnabled; + } + } + + protected void Awake() + { + targetRefreshTimer = 0.5f; + master = GetComponent(); + stateMachine = GetComponent(); + stateMachine.enabled = false; + networkIdentity = GetComponent(); + skillDrivers = GetComponents(); + currentEnemy = new Target(this); + leader = new Target(this); + buddy = new Target(this); + customTarget = new Target(this); + broadNavigationSystem = nodeGraphNavigationSystem; + } + + protected void OnDestroy() + { + broadNavigationSystem = null; + } + + protected void Start() + { + if (!Util.HasEffectiveAuthority(networkIdentity)) + { + base.enabled = false; + if ((bool)stateMachine) + { + stateMachine.enabled = false; + } + } + if (NetworkServer.active) + { + skillDriverUpdateTimer = UnityEngine.Random.value; + } + } + + protected void FixedUpdate() + { + ManagedFixedUpdate(Time.fixedDeltaTime); + } + + public void ManagedFixedUpdate(float deltaTime) + { + enemyAttention -= deltaTime; + targetRefreshTimer -= deltaTime; + skillDriverUpdateTimer -= deltaTime; + if ((bool)body) + { + if (shouldMissFirstOffScreenShot) + { + offScreenUpdateTimer -= deltaTime; + if (offScreenUpdateTimer <= 0f) + { + offScreenUpdateTimer = 0.25f; + shouldMissFirstOffScreenShot = OffScreenMissHelper.IsPositionOffScreen(body.transform.position); + } + } + broadNavigationAgent.ConfigureFromBody(body); + if (skillDriverUpdateTimer <= 0f) + { + if ((bool)skillDriverEvaluation.dominantSkillDriver && skillDriverEvaluation.dominantSkillDriver.resetCurrentEnemyOnNextDriverSelection) + { + currentEnemy.Reset(); + targetRefreshTimer = 0f; + } + if (!currentEnemy.gameObject && targetRefreshTimer <= 0f) + { + targetRefreshTimer = 0.5f; + HurtBox hurtBox = null; + hurtBox = FindEnemyHurtBox(float.PositiveInfinity, fullVision, filterByLoS: true); + if ((bool)hurtBox && (bool)hurtBox.healthComponent) + { + currentEnemy.gameObject = hurtBox.healthComponent.gameObject; + currentEnemy.bestHurtBox = hurtBox; + } + if ((bool)currentEnemy.gameObject) + { + enemyAttention = enemyAttentionDuration; + } + } + BeginSkillDriver(EvaluateSkillDrivers()); + } + } + _broadNavigationAgent.currentPosition = GetNavigationStartPos(); + UpdateBodyInputs(); + UpdateBodyAim(deltaTime); + debugEnemyHurtBox = currentEnemy.bestHurtBox; + } + + private void BeginSkillDriver(SkillDriverEvaluation newSkillDriverEvaluation) + { + if ((bool)skillDriverEvaluation.dominantSkillDriver) + { + _ = skillDriverEvaluation.dominantSkillDriver.customName; + } + skillDriverEvaluation = newSkillDriverEvaluation; + skillDriverUpdateTimer = UnityEngine.Random.Range(1f / 6f, 0.2f); + if ((bool)skillDriverEvaluation.dominantSkillDriver) + { + _ = showDebugStateChanges; + selectedSkilldriverName = skillDriverEvaluation.dominantSkillDriver.customName; + if (skillDriverEvaluation.dominantSkillDriver.driverUpdateTimerOverride >= 0f) + { + skillDriverUpdateTimer = skillDriverEvaluation.dominantSkillDriver.driverUpdateTimerOverride; + } + skillDriverEvaluation.dominantSkillDriver.OnSelected(); + } + else + { + _ = showDebugStateChanges; + selectedSkilldriverName = ""; + } + } + + public virtual void OnBodyStart(CharacterBody newBody) + { + body = newBody; + bodyTransform = newBody.transform; + bodyCharacterDirection = newBody.GetComponent(); + bodyCharacterMotor = newBody.GetComponent(); + bodyInputBank = newBody.GetComponent(); + bodyHealthComponent = newBody.GetComponent(); + bodySkillLocator = newBody.GetComponent(); + localNavigator.SetBody(newBody); + _broadNavigationAgent.enabled = true; + if ((bool)stateMachine && Util.HasEffectiveAuthority(networkIdentity)) + { + stateMachine.enabled = true; + stateMachine.SetNextState(EntityStateCatalog.InstantiateState(ref scanState)); + } + base.enabled = true; + if ((bool)bodyCharacterDirection) + { + bodyInputs.desiredAimDirection = bodyCharacterDirection.forward; + } + else + { + bodyInputs.desiredAimDirection = bodyTransform.forward; + } + if ((bool)bodyInputBank) + { + bodyInputBank.aimDirection = bodyInputs.desiredAimDirection; + } + this.onBodyDiscovered?.Invoke(newBody); + } + + public virtual void OnBodyDeath(CharacterBody characterBody) + { + OnBodyLost(characterBody); + } + + public virtual void OnBodyDestroyed(CharacterBody characterBody) + { + OnBodyLost(characterBody); + } + + public virtual void OnBodyLost(CharacterBody characterBody) + { + if ((object)body != null) + { + base.enabled = false; + body = null; + bodyTransform = null; + bodyCharacterDirection = null; + bodyCharacterMotor = null; + bodyInputBank = null; + bodyHealthComponent = null; + bodySkillLocator = null; + localNavigator.SetBody(null); + _broadNavigationAgent.enabled = false; + if ((bool)stateMachine) + { + stateMachine.enabled = false; + stateMachine.SetNextState(new Idle()); + } + this.onBodyLost?.Invoke(characterBody); + } + } + + public virtual void OnBodyDamaged(DamageReport damageReport) + { + DamageInfo damageInfo = damageReport.damageInfo; + if ((bool)damageInfo.attacker && (bool)body && (!currentEnemy.gameObject || enemyAttention <= 0f) && damageInfo.attacker != body.gameObject && (!neverRetaliateFriendlies || !damageReport.isFriendlyFire)) + { + currentEnemy.gameObject = damageInfo.attacker; + enemyAttention = enemyAttentionDuration; + } + } + + [Obsolete] + public virtual bool HasLOS(Vector3 start, Vector3 end) + { + if (!body) + { + return false; + } + Vector3 direction = end - start; + float magnitude = direction.magnitude; + if (body.visionDistance < magnitude) + { + return false; + } + Ray ray = default(Ray); + ray.origin = start; + ray.direction = direction; + RaycastHit hitInfo; + return !Physics.Raycast(ray, out hitInfo, magnitude, LayerIndex.world.mask); + } + + public virtual bool HasLOS(Vector3 end) + { + if (!body || !bodyInputBank) + { + return false; + } + Vector3 aimOrigin = bodyInputBank.aimOrigin; + Vector3 direction = end - aimOrigin; + float magnitude = direction.magnitude; + if (body.visionDistance < magnitude) + { + return false; + } + Ray ray = default(Ray); + ray.origin = aimOrigin; + ray.direction = direction; + RaycastHit hitInfo; + return !Physics.Raycast(ray, out hitInfo, magnitude, LayerIndex.world.mask); + } + + private Vector3? GetNavigationStartPos() + { + if (!body) + { + return null; + } + return body.footPosition; + } + + public NodeGraph GetDesiredSpawnNodeGraph() + { + return SceneInfo.instance.GetNodeGraph(desiredSpawnNodeGraphType); + } + + public void SetGoalPosition(Vector3? goalPos) + { + BroadNavigationSystem.Agent agent = broadNavigationAgent; + agent.goalPosition = goalPos; + } + + public void SetGoalPosition(Target goalTarget) + { + Vector3? goalPosition = null; + if (goalTarget.GetBullseyePosition(out var position)) + { + Vector3 value = position; + goalPosition = value; + } + SetGoalPosition(goalPosition); + } + + public void DebugDrawPath(Color color, float duration) + { + if (broadNavigationSystem is NodeGraphNavigationSystem) + { + ((NodeGraphNavigationSystem.Agent)broadNavigationAgent).DebugDrawPath(color, duration); + } + } + + private static bool CheckLoS(Vector3 start, Vector3 end) + { + Vector3 direction = end - start; + RaycastHit hitInfo; + return !Physics.Raycast(start, direction, out hitInfo, direction.magnitude, LayerIndex.world.mask, QueryTriggerInteraction.Ignore); + } + + public HurtBox GetBestHurtBox(GameObject target) + { + HurtBoxGroup hurtBoxGroup = target.GetComponent()?.hurtBoxGroup; + if ((bool)hurtBoxGroup && hurtBoxGroup.bullseyeCount > 1 && (bool)bodyInputBank) + { + Vector3 aimOrigin = bodyInputBank.aimOrigin; + HurtBox hurtBox = null; + float num = float.PositiveInfinity; + HurtBox[] hurtBoxes = hurtBoxGroup.hurtBoxes; + foreach (HurtBox hurtBox2 in hurtBoxes) + { + if (!hurtBox2.isBullseye) + { + continue; + } + Vector3 position = hurtBox2.transform.position; + if (CheckLoS(aimOrigin, hurtBox2.transform.position)) + { + float sqrMagnitude = (position - aimOrigin).sqrMagnitude; + if (sqrMagnitude < num) + { + num = sqrMagnitude; + hurtBox = hurtBox2; + } + } + } + if ((bool)hurtBox) + { + return hurtBox; + } + } + return Util.FindBodyMainHurtBox(target); + } + + public void ForceAcquireNearestEnemyIfNoCurrentEnemy() + { + if ((bool)currentEnemy.gameObject) + { + return; + } + if (!body) + { + Debug.LogErrorFormat("BaseAI.ForceAcquireNearestEnemyIfNoCurrentEnemy for CharacterMaster '{0}' failed: AI has no body to search from.", base.gameObject.name); + return; + } + HurtBox hurtBox = FindEnemyHurtBox(float.PositiveInfinity, full360Vision: true, filterByLoS: false); + if ((bool)hurtBox && (bool)hurtBox.healthComponent) + { + currentEnemy.gameObject = hurtBox.healthComponent.gameObject; + currentEnemy.bestHurtBox = hurtBox; + } + } + + private HurtBox FindEnemyHurtBox(float maxDistance, bool full360Vision, bool filterByLoS) + { + if (!body) + { + return null; + } + enemySearch.viewer = body; + enemySearch.teamMaskFilter = TeamMask.allButNeutral; + enemySearch.teamMaskFilter.RemoveTeam(master.teamIndex); + enemySearch.sortMode = BullseyeSearch.SortMode.Distance; + enemySearch.minDistanceFilter = 0f; + enemySearch.maxDistanceFilter = maxDistance; + enemySearch.searchOrigin = bodyInputBank.aimOrigin; + enemySearch.searchDirection = bodyInputBank.aimDirection; + enemySearch.maxAngleFilter = (full360Vision ? 180f : 90f); + enemySearch.filterByLoS = filterByLoS; + enemySearch.RefreshCandidates(); + return enemySearch.GetResults().FirstOrDefault(); + } + + public bool GameObjectPassesSkillDriverFilters(Target target, AISkillDriver skillDriver, out float separationSqrMagnitude) + { + separationSqrMagnitude = 0f; + if (!target.gameObject) + { + return false; + } + float num = 1f; + if ((bool)target.healthComponent) + { + num = target.healthComponent.combinedHealthFraction; + } + if (num < skillDriver.minTargetHealthFraction || num > skillDriver.maxTargetHealthFraction) + { + return false; + } + float num2 = 0f; + if ((bool)body) + { + num2 = body.radius; + } + float num3 = 0f; + if ((bool)target.characterBody) + { + num3 = target.characterBody.radius; + } + Vector3 vector = (bodyInputBank ? bodyInputBank.aimOrigin : bodyTransform.position); + target.GetBullseyePosition(out var position); + float sqrMagnitude = (position - vector).sqrMagnitude; + separationSqrMagnitude = sqrMagnitude - num3 * num3 - num2 * num2; + if (separationSqrMagnitude < skillDriver.minDistanceSqr || separationSqrMagnitude > skillDriver.maxDistanceSqr) + { + return false; + } + if (skillDriver.selectionRequiresTargetLoS && !target.hasLoS) + { + return false; + } + return true; + } + + private void UpdateTargets() + { + currentEnemy.Update(); + leader.Update(); + } + + protected SkillDriverEvaluation? EvaluateSingleSkillDriver(in SkillDriverEvaluation currentSkillDriverEvaluation, AISkillDriver aiSkillDriver, float myHealthFraction) + { + if (!body || !bodySkillLocator) + { + return null; + } + float separationSqrMagnitude = float.PositiveInfinity; + if (aiSkillDriver.noRepeat && currentSkillDriverEvaluation.dominantSkillDriver == aiSkillDriver) + { + return null; + } + if (aiSkillDriver.maxTimesSelected >= 0 && aiSkillDriver.timesSelected >= aiSkillDriver.maxTimesSelected) + { + return null; + } + Target target = null; + if (aiSkillDriver.requireEquipmentReady && body.equipmentSlot.stock <= 0) + { + return null; + } + if (aiSkillDriver.skillSlot != SkillSlot.None) + { + GenericSkill skill = bodySkillLocator.GetSkill(aiSkillDriver.skillSlot); + if (aiSkillDriver.requireSkillReady && (!skill || !skill.IsReady())) + { + return null; + } + if ((bool)aiSkillDriver.requiredSkill && (!skill || !(skill.skillDef == aiSkillDriver.requiredSkill))) + { + return null; + } + } + if (aiSkillDriver.minUserHealthFraction > myHealthFraction || aiSkillDriver.maxUserHealthFraction < myHealthFraction) + { + return null; + } + if ((bool)bodyCharacterMotor && !bodyCharacterMotor.isGrounded && aiSkillDriver.selectionRequiresOnGround) + { + return null; + } + switch (aiSkillDriver.moveTargetType) + { + case AISkillDriver.TargetType.CurrentEnemy: + if (GameObjectPassesSkillDriverFilters(currentEnemy, aiSkillDriver, out separationSqrMagnitude)) + { + target = currentEnemy; + } + break; + case AISkillDriver.TargetType.NearestFriendlyInSkillRange: + if ((bool)bodyInputBank) + { + buddySearch.teamMaskFilter = TeamMask.none; + buddySearch.teamMaskFilter.AddTeam(master.teamIndex); + buddySearch.sortMode = BullseyeSearch.SortMode.Distance; + buddySearch.minDistanceFilter = aiSkillDriver.minDistanceSqr; + buddySearch.maxDistanceFilter = aiSkillDriver.maxDistance; + buddySearch.searchOrigin = bodyInputBank.aimOrigin; + buddySearch.searchDirection = bodyInputBank.aimDirection; + buddySearch.maxAngleFilter = 180f; + buddySearch.filterByLoS = aiSkillDriver.activationRequiresTargetLoS; + buddySearch.RefreshCandidates(); + if ((bool)body) + { + buddySearch.FilterOutGameObject(body.gameObject); + } + buddySearch.FilterCandidatesByHealthFraction(aiSkillDriver.minTargetHealthFraction, aiSkillDriver.maxTargetHealthFraction); + HurtBox hurtBox = buddySearch.GetResults().FirstOrDefault(); + if ((bool)hurtBox && (bool)hurtBox.healthComponent) + { + buddy.gameObject = hurtBox.healthComponent.gameObject; + buddy.bestHurtBox = hurtBox; + } + if (GameObjectPassesSkillDriverFilters(buddy, aiSkillDriver, out separationSqrMagnitude)) + { + target = buddy; + } + } + break; + case AISkillDriver.TargetType.CurrentLeader: + if (GameObjectPassesSkillDriverFilters(leader, aiSkillDriver, out separationSqrMagnitude)) + { + target = leader; + } + break; + case AISkillDriver.TargetType.Custom: + if (GameObjectPassesSkillDriverFilters(customTarget, aiSkillDriver, out separationSqrMagnitude)) + { + target = customTarget; + } + break; + } + if (target == null) + { + return null; + } + Target target2 = null; + if (aiSkillDriver.aimType != 0) + { + bool flag = aiSkillDriver.selectionRequiresAimTarget; + switch (aiSkillDriver.aimType) + { + case AISkillDriver.AimType.AtMoveTarget: + target2 = target; + break; + case AISkillDriver.AimType.AtCurrentEnemy: + target2 = currentEnemy; + break; + case AISkillDriver.AimType.AtCurrentLeader: + target2 = leader; + break; + default: + flag = false; + break; + } + if (flag && (target2 == null || !target2.gameObject)) + { + return null; + } + } + SkillDriverEvaluation value = default(SkillDriverEvaluation); + value.dominantSkillDriver = aiSkillDriver; + value.target = target; + value.aimTarget = target2; + value.separationSqrMagnitude = separationSqrMagnitude; + return value; + } + + public SkillDriverEvaluation EvaluateSkillDrivers() + { + UpdateTargets(); + float myHealthFraction = 1f; + if ((bool)bodyHealthComponent) + { + myHealthFraction = bodyHealthComponent.combinedHealthFraction; + } + if ((bool)bodySkillLocator) + { + if ((bool)this.skillDriverEvaluation.dominantSkillDriver && (bool)this.skillDriverEvaluation.dominantSkillDriver.nextHighPriorityOverride) + { + SkillDriverEvaluation? skillDriverEvaluation = EvaluateSingleSkillDriver(in this.skillDriverEvaluation, this.skillDriverEvaluation.dominantSkillDriver.nextHighPriorityOverride, myHealthFraction); + if (skillDriverEvaluation.HasValue) + { + return skillDriverEvaluation.Value; + } + } + for (int i = 0; i < skillDrivers.Length; i++) + { + AISkillDriver aISkillDriver = skillDrivers[i]; + if (aISkillDriver.enabled) + { + SkillDriverEvaluation? skillDriverEvaluation2 = EvaluateSingleSkillDriver(in this.skillDriverEvaluation, aISkillDriver, myHealthFraction); + if (skillDriverEvaluation2.HasValue) + { + return skillDriverEvaluation2.Value; + } + } + } + } + return default(SkillDriverEvaluation); + } + + protected void UpdateBodyInputs() + { + if (stateMachine.state is BaseAIState baseAIState) + { + bodyInputs = baseAIState.GenerateBodyInputs(in bodyInputs); + } + if ((bool)bodyInputBank) + { + bodyInputBank.skill1.PushState(bodyInputs.pressSkill1); + bodyInputBank.skill2.PushState(bodyInputs.pressSkill2); + bodyInputBank.skill3.PushState(bodyInputs.pressSkill3); + bodyInputBank.skill4.PushState(bodyInputs.pressSkill4); + bodyInputBank.jump.PushState(bodyInputs.pressJump); + bodyInputBank.sprint.PushState(bodyInputs.pressSprint); + bodyInputBank.activateEquipment.PushState(bodyInputs.pressActivateEquipment); + bodyInputBank.moveVector = bodyInputs.moveVector; + } + } + + protected void UpdateBodyAim(float deltaTime) + { + hasAimConfirmation = false; + if ((bool)bodyInputBank) + { + Vector3 aimDirection = bodyInputBank.aimDirection; + Vector3 desiredAimDirection = bodyInputs.desiredAimDirection; + if (desiredAimDirection != Vector3.zero) + { + Quaternion target = Util.QuaternionSafeLookRotation(desiredAimDirection); + Vector3 vector = Util.SmoothDampQuaternion(Util.QuaternionSafeLookRotation(aimDirection), maxSpeed: aimVectorMaxSpeed, target: target, currentVelocity: ref aimVelocity, smoothTime: aimVectorDampTime, deltaTime: deltaTime) * Vector3.forward; + bodyInputBank.aimDirection = vector; + hasAimConfirmation = Vector3.Dot(vector, desiredAimDirection) >= 0.95f; + } + } + } + + [ConCommand(commandName = "ai_draw_path", flags = ConVarFlags.Cheat, helpText = "Enables or disables the drawing of the specified AI's broad navigation path. Format: ai_draw_path <0/1>")] + private static void CCAiDrawPath(ConCommandArgs args) + { + CharacterMaster argCharacterMasterInstance = args.GetArgCharacterMasterInstance(0); + args.GetArgBool(1); + if (!argCharacterMasterInstance) + { + throw new ConCommandException("Could not find target."); + } + BaseAI component = argCharacterMasterInstance.GetComponent(); + if (!component) + { + throw new ConCommandException("Target has no AI."); + } + component.ToggleBroadNavigationDebugDraw(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterAI/EmergencyDroneCustomTarget.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/EmergencyDroneCustomTarget.cs new file mode 100644 index 0000000..e4e2f75 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/EmergencyDroneCustomTarget.cs @@ -0,0 +1,86 @@ +using System.Linq; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.CharacterAI; + +[RequireComponent(typeof(BaseAI))] +public class EmergencyDroneCustomTarget : MonoBehaviour +{ + private BaseAI ai; + + private BullseyeSearch search; + + public float searchInterval; + + private float timer; + + private void Awake() + { + ai = GetComponent(); + if (NetworkServer.active) + { + search = new BullseyeSearch(); + } + } + + private void FixedUpdate() + { + if (NetworkServer.active) + { + FixedUpdateServer(); + } + } + + private void FixedUpdateServer() + { + timer -= Time.fixedDeltaTime; + if (timer <= 0f) + { + timer = searchInterval; + DoSearch(); + } + } + + private void DoSearch() + { + if ((bool)ai.body) + { + Ray aimRay = ai.bodyInputBank.GetAimRay(); + search.viewer = ai.body; + search.filterByDistinctEntity = true; + search.filterByLoS = false; + search.maxDistanceFilter = float.PositiveInfinity; + search.minDistanceFilter = 0f; + search.maxAngleFilter = 360f; + search.searchDirection = aimRay.direction; + search.searchOrigin = aimRay.origin; + search.sortMode = BullseyeSearch.SortMode.Distance; + search.queryTriggerInteraction = QueryTriggerInteraction.UseGlobal; + TeamMask none = TeamMask.none; + none.AddTeam(ai.master.teamIndex); + search.teamMaskFilter = none; + search.RefreshCandidates(); + search.FilterOutGameObject(ai.body.gameObject); + ai.customTarget.gameObject = search.GetResults().Where(TargetPassesFilters).FirstOrDefault()?.healthComponent.gameObject; + } + } + + private bool TargetPassesFilters(HurtBox hurtBox) + { + if (IsHurt(hurtBox)) + { + return !HealBeamController.HealBeamAlreadyExists(ai.body.gameObject, hurtBox.healthComponent); + } + return false; + } + + private static bool IsHurt(HurtBox hurtBox) + { + if (hurtBox.healthComponent.alive) + { + return hurtBox.healthComponent.health < hurtBox.healthComponent.fullHealth; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterAI/LemurianEggController.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/LemurianEggController.cs new file mode 100644 index 0000000..fff3597 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterAI/LemurianEggController.cs @@ -0,0 +1,203 @@ +using System.Collections; +using RoR2.Networking; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.CharacterAI; + +public class LemurianEggController : NetworkBehaviour +{ + private static float itemVFXDuration; + + [Tooltip("The master to spawn")] + public GameObject masterPrefab; + + public SfxLocator sfxLocator; + + private Interactor interactor; + + private static int kCmdCmdOfferItem; + + public void SetInteractability(bool interactable) + { + PickupPickerController component = GetComponent(); + if ((bool)component) + { + component.SetAvailable(interactable); + } + } + + private void OnEnable() + { + InstanceTracker.Add(this); + } + + private void OnDisable() + { + InstanceTracker.Remove(this); + } + + [Server] + public void AssignPotentialInteractor(Interactor potentialInteractor) + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.CharacterAI.LemurianEggController::AssignPotentialInteractor(RoR2.Interactor)' called on client"); + } + else + { + interactor = potentialInteractor; + } + } + + public override int GetNetworkChannel() + { + return QosChannelIndex.defaultReliable.intVal; + } + + [Server] + private void OfferItem(int intPickupIndex) + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.CharacterAI.LemurianEggController::OfferItem(System.Int32)' called on client"); + return; + } + PickupIndex pickupIndex = new PickupIndex(intPickupIndex); + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + if (pickupDef != null && (bool)interactor) + { + CharacterBody component = interactor.GetComponent(); + if ((bool)component && (bool)component.inventory && component.inventory.GetItemCount(pickupDef.itemIndex) > 0) + { + component.inventory.RemoveItem(pickupDef.itemIndex); + CreateItemTakenOrb(component.corePosition, base.gameObject, pickupDef.itemIndex); + GetComponent().SetAvailable(newAvailable: false); + StartCoroutine(WaitToSummonLemurian(pickupIndex)); + } + } + } + + [Command] + public void CmdOfferItem(int intPickupIndex) + { + OfferItem(intPickupIndex); + } + + [Server] + public void CreateItemTakenOrb(Vector3 effectOrigin, GameObject targetObject, ItemIndex itemIndex) + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.CharacterAI.LemurianEggController::CreateItemTakenOrb(UnityEngine.Vector3,UnityEngine.GameObject,RoR2.ItemIndex)' called on client"); + return; + } + EffectData effectData = new EffectData + { + origin = effectOrigin, + genericFloat = itemVFXDuration, + genericUInt = (uint)(itemIndex + 1) + }; + effectData.SetNetworkedObjectReference(targetObject); + EffectManager.SpawnEffect(DevotionInventoryController.s_effectPrefab, effectData, transmit: true); + } + + private IEnumerator WaitToSummonLemurian(PickupIndex pickupIndex) + { + yield return new WaitForSeconds(itemVFXDuration); + SummonLemurian(pickupIndex); + } + + [Server] + private void SummonLemurian(PickupIndex pickupIndex) + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.CharacterAI.LemurianEggController::SummonLemurian(RoR2.PickupIndex)' called on client"); + return; + } + float num = 0f; + CharacterMaster characterMaster = new MasterSummon + { + masterPrefab = masterPrefab, + position = base.transform.position + Vector3.up * num, + rotation = base.transform.rotation, + summonerBodyObject = interactor?.gameObject, + ignoreTeamMemberLimit = true, + useAmbientLevel = true + }.Perform(); + EffectData effectData = new EffectData + { + origin = base.gameObject.transform.position + }; + if ((bool)characterMaster) + { + interactor.GetComponent(); + DevotionInventoryController orCreateDevotionInventoryController = DevotionInventoryController.GetOrCreateDevotionInventoryController(interactor); + characterMaster.GetComponent().InitializeDevotedLemurian(pickupIndex.itemIndex, orCreateDevotionInventoryController); + orCreateDevotionInventoryController.GiveItem(pickupIndex.itemIndex); + orCreateDevotionInventoryController.UpdateAllMinions(); + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/LemurianEggHatching"), effectData, transmit: true); + } + Object.Destroy(base.gameObject); + } + + static LemurianEggController() + { + itemVFXDuration = 1.5f; + kCmdCmdOfferItem = -1179441837; + NetworkBehaviour.RegisterCommandDelegate(typeof(LemurianEggController), kCmdCmdOfferItem, InvokeCmdCmdOfferItem); + NetworkCRC.RegisterBehaviour("LemurianEggController", 0); + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdOfferItem(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdOfferItem called on client."); + } + else + { + ((LemurianEggController)obj).CmdOfferItem((int)reader.ReadPackedUInt32()); + } + } + + public void CallCmdOfferItem(int intPickupIndex) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdOfferItem called on server."); + return; + } + if (base.isServer) + { + CmdOfferItem(intPickupIndex); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdOfferItem); + networkWriter.Write(GetComponent().netId); + networkWriter.WritePackedUInt32((uint)intPickupIndex); + SendCommandInternal(networkWriter, 0, "CmdOfferItem"); + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool result = default(bool); + return result; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/BaseCharacterSpeechDriver.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/BaseCharacterSpeechDriver.cs new file mode 100644 index 0000000..1e74fef --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/BaseCharacterSpeechDriver.cs @@ -0,0 +1,65 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.CharacterSpeech; + +[RequireComponent(typeof(CharacterSpeechController))] +public class BaseCharacterSpeechDriver : MonoBehaviour +{ + protected CharacterSpeechController characterSpeechController { get; private set; } + + protected CharacterBody currentCharacterBody { get; private set; } + + protected void Awake() + { + if (!NetworkServer.active) + { + base.enabled = false; + } + else + { + characterSpeechController = GetComponent(); + } + } + + protected void OnEnable() + { + if (NetworkServer.active) + { + characterSpeechController.onCharacterBodyDiscovered += OnCharacterBodyDiscovered; + characterSpeechController.onCharacterBodyLost += OnCharacterBodyLost; + if ((object)characterSpeechController.currentCharacterBody != null) + { + OnCharacterBodyDiscovered(characterSpeechController.currentCharacterBody); + } + } + } + + protected void OnDisable() + { + if (NetworkServer.active) + { + if ((object)currentCharacterBody != null) + { + OnCharacterBodyLost(currentCharacterBody); + } + characterSpeechController.onCharacterBodyLost -= OnCharacterBodyLost; + characterSpeechController.onCharacterBodyDiscovered -= OnCharacterBodyDiscovered; + } + } + + protected void OnDestroy() + { + _ = NetworkServer.active; + } + + protected virtual void OnCharacterBodyDiscovered(CharacterBody characterBody) + { + currentCharacterBody = characterBody; + } + + protected virtual void OnCharacterBodyLost(CharacterBody characterBody) + { + currentCharacterBody = null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/BrotherSpeechDriver.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/BrotherSpeechDriver.cs new file mode 100644 index 0000000..964e244 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/BrotherSpeechDriver.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.ObjectModel; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.CharacterSpeech; + +[RequireComponent(typeof(CharacterSpeechController))] +[RequireComponent(typeof(SimpleCombatSpeechDriver))] +public class BrotherSpeechDriver : BaseCharacterSpeechDriver +{ + public CharacterSpeechController.SpeechInfo[] seeHereticResponses; + + public CharacterSpeechController.SpeechInfo[] seeTitanGoldResponses; + + public CharacterSpeechController.SpeechInfo[] seeHereticAndTitanGoldResponses; + + public CharacterSpeechController.SpeechInfo[] killMechanicalResponses; + + public CharacterSpeechController.SpeechInfo[] killHereticResponses; + + public CharacterSpeechController.SpeechInfo[] killTitanGoldReponses; + + public UnityEvent onTitanGoldSighted; + + private SimpleCombatSpeechDriver simpleCombatSpeechDriver; + + private static BodyIndex hereticBodyIndex = BodyIndex.None; + + private static BodyIndex titanGoldBodyIndex = BodyIndex.None; + + [SystemInitializer(new Type[] { typeof(BodyCatalog) })] + private static void Init() + { + hereticBodyIndex = BodyCatalog.FindBodyIndex("HereticBody"); + titanGoldBodyIndex = BodyCatalog.FindBodyIndex("TitanGoldBody"); + } + + protected new void Awake() + { + base.Awake(); + if (NetworkServer.active) + { + simpleCombatSpeechDriver = GetComponent(); + simpleCombatSpeechDriver.onBodyKill.AddListener(OnBodyKill); + CharacterBody.onBodyStartGlobal += OnCharacterBodyStartGlobal; + } + } + + protected new void OnDestroy() + { + CharacterBody.onBodyStartGlobal -= OnCharacterBodyStartGlobal; + base.OnDestroy(); + } + + private void OnCharacterBodyStartGlobal(CharacterBody characterBody) + { + if (characterBody.bodyIndex == titanGoldBodyIndex) + { + onTitanGoldSighted?.Invoke(); + } + } + + public void DoInitialSightResponse() + { + bool flag = false; + bool flag2 = false; + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + BodyIndex bodyIndex = readOnlyInstancesList[i].bodyIndex; + flag |= bodyIndex == hereticBodyIndex; + flag2 |= bodyIndex == titanGoldBodyIndex; + } + CharacterSpeechController.SpeechInfo[] responsePool = Array.Empty(); + if (flag && flag2) + { + TrySetResponsePool(seeHereticAndTitanGoldResponses); + } + if (flag) + { + TrySetResponsePool(seeHereticResponses); + } + if (flag2) + { + TrySetResponsePool(seeTitanGoldResponses); + } + SendReponseFromPool(responsePool); + void TrySetResponsePool(CharacterSpeechController.SpeechInfo[] newResponsePool) + { + if (responsePool.Length == 0) + { + responsePool = newResponsePool; + } + } + } + + private void OnBodyKill(DamageReport damageReport) + { + CharacterSpeechController.SpeechInfo[] responsePool; + if ((bool)damageReport.victimBody) + { + responsePool = Array.Empty(); + if (damageReport.victimBodyIndex == hereticBodyIndex) + { + TrySetResponsePool(killHereticResponses); + } + else if (damageReport.victimBodyIndex == titanGoldBodyIndex) + { + TrySetResponsePool(killTitanGoldReponses); + } + else if ((damageReport.victimBody.bodyFlags &= CharacterBody.BodyFlags.Mechanical) == CharacterBody.BodyFlags.Mechanical && killMechanicalResponses.Length != 0) + { + TrySetResponsePool(killMechanicalResponses); + } + SendReponseFromPool(responsePool); + } + void TrySetResponsePool(CharacterSpeechController.SpeechInfo[] newResponsePool) + { + if (responsePool.Length == 0) + { + responsePool = newResponsePool; + } + } + } + + private void SendReponseFromPool(CharacterSpeechController.SpeechInfo[] responsePool) + { + if (responsePool.Length != 0) + { + base.characterSpeechController.EnqueueSpeech(in responsePool[UnityEngine.Random.Range(0, responsePool.Length - 1)]); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/CharacterSpeechController.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/CharacterSpeechController.cs new file mode 100644 index 0000000..5b99b2d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/CharacterSpeechController.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Generic; +using RoR2.ConVar; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.CharacterSpeech; + +public class CharacterSpeechController : MonoBehaviour +{ + [Serializable] + public struct SpeechInfo + { + public string token; + + public float duration; + + public float maxWait; + + public float priority; + + public bool mustPlay; + + public override string ToString() + { + return $"{{ token=\"{token}\" duration={duration} maxWait={maxWait} priority={priority} mustPlay={mustPlay} }}"; + } + } + + [Serializable] + private struct SpeechRequest + { + public SpeechInfo speechInfo; + + public float submitTime; + + public override string ToString() + { + return $"{{ speechInfo={speechInfo} submitTime={submitTime} }}"; + } + } + + public CharacterMaster initialCharacterMaster; + + public string chatFormatToken; + + private float localTime; + + private float nextSpeakTime; + + private List speechRequestQueue; + + private CharacterMaster _characterMaster; + + private CharacterBody _currentCharacterBody; + + private static readonly BoolConVar cvEnableLogging = new BoolConVar("character_speech_debug", ConVarFlags.None, "0", "Enables/disables debug logging for CharacterSpeechController"); + + public CharacterMaster characterMaster + { + get + { + return _characterMaster; + } + set + { + if ((object)_characterMaster != value) + { + if ((object)_characterMaster != null) + { + OnCharacterMasterLost(_characterMaster); + } + _characterMaster = value; + if ((object)_characterMaster != null) + { + OnCharacterMasterDiscovered(_characterMaster); + } + } + } + } + + public CharacterBody currentCharacterBody + { + get + { + return _currentCharacterBody; + } + private set + { + if ((object)_currentCharacterBody != value) + { + if ((object)_currentCharacterBody != null) + { + OnCharacterBodyLost(_currentCharacterBody); + } + _currentCharacterBody = value; + if ((object)_currentCharacterBody != null) + { + OnCharacterBodyDiscovered(_currentCharacterBody); + } + } + } + } + + public event Action onCharacterMasterDiscovered; + + public event Action onCharacterMasterLost; + + public event Action onCharacterBodyDiscovered; + + public event Action onCharacterBodyLost; + + private void Awake() + { + if (!NetworkServer.active) + { + base.enabled = false; + } + else + { + speechRequestQueue = new List(); + } + } + + private void Start() + { + if ((object)characterMaster == null) + { + characterMaster = initialCharacterMaster; + } + } + + private void FixedUpdate() + { + Process(Time.fixedDeltaTime); + } + + private void OnDestroy() + { + if (NetworkServer.active) + { + characterMaster = null; + } + } + + public void SpeakNow(in SpeechInfo speechInfo) + { + if (!NetworkServer.active) + { + return; + } + if (cvEnableLogging.value) + { + Log($"Playing speech: {speechInfo}"); + } + nextSpeakTime = localTime + speechInfo.duration; + CharacterBody characterBody = null; + GameObject sender = null; + SfxLocator sfxLocator = null; + if ((bool)characterMaster) + { + characterBody = characterMaster.GetBody(); + if ((bool)characterBody) + { + sfxLocator = characterBody.GetComponent(); + } + } + Chat.SendBroadcastChat(new Chat.NpcChatMessage + { + baseToken = speechInfo.token, + formatStringToken = chatFormatToken, + sender = sender, + sound = sfxLocator?.barkSound + }); + } + + public void EnqueueSpeech(in SpeechInfo speechInfo) + { + if (NetworkServer.active) + { + SpeechRequest speechRequest = default(SpeechRequest); + speechRequest.speechInfo = speechInfo; + speechRequest.submitTime = localTime; + SpeechRequest speechRequest2 = speechRequest; + speechRequestQueue.Add(speechRequest2); + if (cvEnableLogging.value) + { + Log($"Enqueued speech: {speechRequest2}"); + } + } + } + + private void Process(float deltaTime) + { + localTime += deltaTime; + if (!(nextSpeakTime <= localTime)) + { + return; + } + int bestNextRequestIndex = GetBestNextRequestIndex(); + if (bestNextRequestIndex == -1) + { + return; + } + SpeechRequest speechRequest = speechRequestQueue[bestNextRequestIndex]; + if (cvEnableLogging.value) + { + Log($"Found best request: bestNextRequestIndex={bestNextRequestIndex} bestNextRequest={speechRequest}"); + for (int i = 0; i < bestNextRequestIndex; i++) + { + Log($"Dropping request: i={i} request={speechRequestQueue[i]}"); + } + } + speechRequestQueue.RemoveRange(0, bestNextRequestIndex + 1); + SpeakNow(in speechRequest.speechInfo); + } + + private int GetBestNextRequestIndex() + { + if (speechRequestQueue.Count == 0) + { + return -1; + } + for (int i = 0; i < speechRequestQueue.Count; i++) + { + SpeechRequest speechRequest = speechRequestQueue[i]; + SpeechInfo speechInfo = speechRequest.speechInfo; + if (speechInfo.mustPlay) + { + return i; + } + float num = speechRequest.submitTime + speechInfo.maxWait; + if (localTime > num) + { + continue; + } + float num2 = localTime + speechInfo.duration; + bool flag = false; + for (int j = i + 1; j < speechRequestQueue.Count; j++) + { + SpeechRequest speechRequest2 = speechRequestQueue[j]; + SpeechInfo speechInfo2 = speechRequest2.speechInfo; + if (!(speechInfo.priority >= speechInfo2.priority) || speechInfo2.mustPlay) + { + if (speechRequest2.submitTime + speechInfo2.maxWait < num2) + { + flag = true; + break; + } + num2 += speechInfo2.duration; + } + } + if (!flag) + { + return i; + } + } + return -1; + } + + private void OnCharacterMasterDiscovered(CharacterMaster characterMaster) + { + characterMaster.onBodyStart += OnCharacterMasterBodyStart; + this.onCharacterMasterDiscovered?.Invoke(characterMaster); + currentCharacterBody = characterMaster.GetBody(); + } + + private void OnCharacterMasterLost(CharacterMaster characterMaster) + { + currentCharacterBody = null; + this.onCharacterMasterLost?.Invoke(characterMaster); + characterMaster.onBodyDestroyed -= OnCharacterMasterBodyDestroyed; + } + + private void OnCharacterMasterBodyStart(CharacterBody characterBody) + { + currentCharacterBody = characterBody; + } + + private void OnCharacterMasterBodyDestroyed(CharacterBody characterBody) + { + if ((object)characterBody == currentCharacterBody) + { + currentCharacterBody = null; + } + } + + private void OnCharacterBodyDiscovered(CharacterBody characterBody) + { + this.onCharacterBodyDiscovered?.Invoke(characterBody); + } + + private void OnCharacterBodyLost(CharacterBody characterBody) + { + this.onCharacterBodyLost?.Invoke(characterBody); + } + + private void Log(string str) + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/FalseSonBossSpeechDriver.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/FalseSonBossSpeechDriver.cs new file mode 100644 index 0000000..96e7e4c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/FalseSonBossSpeechDriver.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.ObjectModel; +using EntityStates.FalseSonBoss; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.CharacterSpeech; + +[RequireComponent(typeof(CharacterSpeechController))] +[RequireComponent(typeof(SimpleCombatSpeechDriver))] +public class FalseSonBossSpeechDriver : BaseCharacterSpeechDriver +{ + public CharacterSpeechController.SpeechInfo[] seeHereticResponses; + + public CharacterSpeechController.SpeechInfo[] seeTitanGoldResponses; + + public CharacterSpeechController.SpeechInfo[] seeHereticAndTitanGoldResponses; + + public CharacterSpeechController.SpeechInfo[] killMechanicalResponses; + + public CharacterSpeechController.SpeechInfo[] killHereticResponses; + + public CharacterSpeechController.SpeechInfo[] killTitanGoldReponses; + + public CharacterSpeechController.SpeechInfo[] killPlayerWithLightningResponses; + + public CharacterSpeechController.SpeechInfo[] purifyFalseSonResponses; + + public UnityEvent onTitanGoldSighted; + + private SimpleCombatSpeechDriver simpleCombatSpeechDriver; + + private static BodyIndex hereticBodyIndex = BodyIndex.None; + + private static BodyIndex titanGoldBodyIndex = BodyIndex.None; + + [SystemInitializer(new Type[] { typeof(BodyCatalog) })] + private static void Init() + { + hereticBodyIndex = BodyCatalog.FindBodyIndex("HereticBody"); + titanGoldBodyIndex = BodyCatalog.FindBodyIndex("TitanGoldBody"); + } + + protected new void Awake() + { + base.Awake(); + if (NetworkServer.active) + { + simpleCombatSpeechDriver = GetComponent(); + simpleCombatSpeechDriver.onBodyKill.AddListener(OnBodyKill); + simpleCombatSpeechDriver.onBossAllyDeath.AddListener(OnBossAllyDeath); + CharacterBody.onBodyStartGlobal += OnCharacterBodyStartGlobal; + SkyJumpDeathState.falseSonUnlockEvent += FalseSonPurifiedResponse; + } + } + + protected new void OnDestroy() + { + CharacterBody.onBodyStartGlobal -= OnCharacterBodyStartGlobal; + SkyJumpDeathState.falseSonUnlockEvent -= FalseSonPurifiedResponse; + base.OnDestroy(); + } + + private void OnCharacterBodyStartGlobal(CharacterBody characterBody) + { + if (characterBody.bodyIndex == titanGoldBodyIndex) + { + onTitanGoldSighted?.Invoke(); + } + } + + public void DoInitialSightResponse() + { + bool flag = false; + bool flag2 = false; + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + BodyIndex bodyIndex = readOnlyInstancesList[i].bodyIndex; + flag |= bodyIndex == hereticBodyIndex; + flag2 |= bodyIndex == titanGoldBodyIndex; + } + CharacterSpeechController.SpeechInfo[] responsePool = Array.Empty(); + if (flag && flag2) + { + TrySetResponsePool(seeHereticAndTitanGoldResponses); + } + if (flag) + { + TrySetResponsePool(seeHereticResponses); + } + if (flag2) + { + TrySetResponsePool(seeTitanGoldResponses); + } + SendReponseFromPool(responsePool); + void TrySetResponsePool(CharacterSpeechController.SpeechInfo[] newResponsePool) + { + if (responsePool.Length == 0) + { + responsePool = newResponsePool; + } + } + } + + private void OnBodyKill(DamageReport damageReport) + { + if (!damageReport.victimBody) + { + return; + } + CharacterSpeechController.SpeechInfo[] responsePool = Array.Empty(); + if (damageReport.victimBodyIndex == hereticBodyIndex) + { + TrySetResponsePool(killHereticResponses); + } + else if ((damageReport.victimBody.bodyFlags &= CharacterBody.BodyFlags.Mechanical) == CharacterBody.BodyFlags.Mechanical) + { + if (killMechanicalResponses.Length != 0) + { + TrySetResponsePool(killMechanicalResponses); + } + } + else if ((ulong)(damageReport.damageInfo.damageType & DamageType.LunarRuin) != 0 && damageReport.attacker == null) + { + TrySetResponsePool(killPlayerWithLightningResponses); + } + SendReponseFromPool(responsePool); + void TrySetResponsePool(CharacterSpeechController.SpeechInfo[] newResponsePool) + { + if (responsePool.Length == 0) + { + responsePool = newResponsePool; + } + } + } + + private void OnBossAllyDeath(DamageReport damageReport) + { + CharacterSpeechController.SpeechInfo[] responsePool; + if ((bool)damageReport.victimBody) + { + responsePool = Array.Empty(); + if (damageReport.victimBodyIndex == titanGoldBodyIndex) + { + TrySetResponsePool(killTitanGoldReponses); + } + SendReponseFromPool(responsePool); + } + void TrySetResponsePool(CharacterSpeechController.SpeechInfo[] newResponsePool) + { + if (responsePool.Length == 0) + { + responsePool = newResponsePool; + } + } + } + + private void FalseSonPurifiedResponse() + { + CharacterSpeechController.SpeechInfo[] responsePool = Array.Empty(); + TrySetResponsePool(purifyFalseSonResponses); + SendReponseFromPool(responsePool); + void TrySetResponsePool(CharacterSpeechController.SpeechInfo[] newResponsePool) + { + if (responsePool.Length == 0) + { + responsePool = newResponsePool; + } + } + } + + private void SendReponseFromPool(CharacterSpeechController.SpeechInfo[] responsePool) + { + if (responsePool.Length != 0) + { + base.characterSpeechController.EnqueueSpeech(in responsePool[UnityEngine.Random.Range(0, responsePool.Length - 1)]); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/SimpleCombatSpeechDriver.cs b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/SimpleCombatSpeechDriver.cs new file mode 100644 index 0000000..a45d7f0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.CharacterSpeech/SimpleCombatSpeechDriver.cs @@ -0,0 +1,255 @@ +using System; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.CharacterSpeech; + +[RequireComponent(typeof(CharacterSpeechController))] +public class SimpleCombatSpeechDriver : BaseCharacterSpeechDriver +{ + [Serializable] + public struct SpeechCategory + { + public string refName; + + public float chanceToTrigger; + + public SpeechInfo[] speechInfos; + + public WeightedSelection speechSelection; + } + + [Serializable] + public struct SpeechInfo + { + public string nameToken; + + public float weight; + } + + [Header("Speech Info")] + public float minimumDurationBetweenSpeech; + + public bool removeRepeats; + + [SerializeField] + public SpeechCategory[] speechCategories; + + [Tooltip("The refname to automatically submit speech for when damage is dealt.")] + public string damageDealtRefName; + + [Header("Combat Parameters")] + public bool scaleChanceOnDamageDealtByHealthFractionDealt = true; + + public float scaleChanceOnDamageDealtMultiplier = 1f; + + [Header("Events")] + public DamageReportUnityEvent onBodyDamageDealt; + + public UnityEvent onStart; + + public DamageReportUnityEvent onBodyKill; + + public DamageReportUnityEvent onBodyDeath; + + public DamageReportUnityEvent onBossAllyDeath; + + private float lastSpeechStopwatch = float.PositiveInfinity; + + protected new void Awake() + { + base.Awake(); + } + + protected void Start() + { + if (NetworkServer.active) + { + Initialize(); + onStart?.Invoke(); + } + } + + protected new void OnDestroy() + { + base.OnDestroy(); + } + + protected void FixedUpdate() + { + lastSpeechStopwatch += Time.fixedDeltaTime; + } + + public void TriggerSpeech(string refName) + { + if (lastSpeechStopwatch < minimumDurationBetweenSpeech) + { + return; + } + int num = FindSpeechCategoryIndexByName(refName); + if (num == -1) + { + Debug.LogWarningFormat("Speech category \"{0}\" could not be found.", refName); + return; + } + ref SpeechCategory reference = ref speechCategories[num]; + if (UnityEngine.Random.value < reference.chanceToTrigger) + { + SubmitSpeechRequestFromCategory(ref reference); + } + } + + private void SubmitSpeechRequestFromCategory(ref SpeechCategory category) + { + if (category.speechSelection == null || category.speechSelection.Count <= 0) + { + if (category.speechInfos.Length == 0) + { + return; + } + InitializeCategory(ref category); + } + int num = category.speechSelection.EvaluateToChoiceIndex(UnityEngine.Random.value); + SpeechInfo value = category.speechSelection.GetChoice(num).value; + if (removeRepeats) + { + category.speechSelection.RemoveChoice(num); + } + lastSpeechStopwatch = 0f; + CharacterSpeechController obj = base.characterSpeechController; + CharacterSpeechController.SpeechInfo speechInfo = new CharacterSpeechController.SpeechInfo + { + token = value.nameToken, + duration = minimumDurationBetweenSpeech, + maxWait = minimumDurationBetweenSpeech, + mustPlay = false + }; + obj.EnqueueSpeech(in speechInfo); + } + + private int FindSpeechCategoryIndexByName(string refName) + { + for (int i = 0; i < speechCategories.Length; i++) + { + if (string.Equals(speechCategories[i].refName, refName, StringComparison.Ordinal)) + { + return i; + } + } + return -1; + } + + private void Initialize() + { + for (int i = 0; i < speechCategories.Length; i++) + { + InitializeCategory(ref speechCategories[i]); + } + } + + private void InitializeCategory(ref SpeechCategory speechCategory) + { + WeightedSelection weightedSelection = new WeightedSelection(); + for (int i = 0; i < speechCategory.speechInfos.Length; i++) + { + SpeechInfo value = speechCategory.speechInfos[i]; + weightedSelection.AddChoice(value, value.weight); + } + speechCategory.speechSelection = weightedSelection; + } + + protected override void OnCharacterBodyDiscovered(CharacterBody characterBody) + { + base.OnCharacterBodyDiscovered(characterBody); + GlobalEventManager.onServerDamageDealt += OnServerDamageDealt; + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + } + + protected override void OnCharacterBodyLost(CharacterBody characterBody) + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + GlobalEventManager.onServerDamageDealt -= OnServerDamageDealt; + base.OnCharacterBodyLost(characterBody); + } + + private void OnServerDamageDealt(DamageReport damageReport) + { + if ((object)damageReport.attackerBody == base.currentCharacterBody) + { + OnBodyDamageDealt(damageReport); + } + if ((object)damageReport.victimBody == base.currentCharacterBody) + { + OnBodyDamageTaken(damageReport); + } + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + CharacterBody characterBody = base.currentCharacterBody; + if (!(characterBody == null)) + { + if ((object)damageReport.attackerBody == characterBody) + { + OnBodyKill(damageReport); + } + if ((object)damageReport.victimBody == characterBody) + { + OnBodyDeath(damageReport); + } + else if (damageReport.victimBody.teamComponent.teamIndex == characterBody.teamComponent.teamIndex) + { + OnBossAllyDeath(damageReport); + } + } + } + + private void OnBodyDamageDealt(DamageReport damageReport) + { + if (scaleChanceOnDamageDealtByHealthFractionDealt && (bool)damageReport.victim && !string.IsNullOrEmpty(damageDealtRefName)) + { + int num = FindSpeechCategoryIndexByName(damageDealtRefName); + if (num == -1) + { + Debug.LogWarningFormat("Speech category \"{0}\" could not be found.", damageDealtRefName); + } + else + { + ref SpeechCategory reference = ref speechCategories[num]; + float num2 = reference.chanceToTrigger; + if (scaleChanceOnDamageDealtByHealthFractionDealt) + { + float fullCombinedHealth = damageReport.victim.fullCombinedHealth; + float num3 = damageReport.damageDealt / fullCombinedHealth; + num2 *= num3; + } + num2 *= scaleChanceOnDamageDealtMultiplier; + if (UnityEngine.Random.value < num2) + { + SubmitSpeechRequestFromCategory(ref reference); + } + } + } + onBodyDamageDealt?.Invoke(damageReport); + } + + private void OnBodyDamageTaken(DamageReport damageReport) + { + } + + private void OnBodyKill(DamageReport damageReport) + { + onBodyKill?.Invoke(damageReport); + } + + private void OnBodyDeath(DamageReport damageReport) + { + onBodyDeath?.Invoke(damageReport); + } + + private void OnBossAllyDeath(DamageReport damageReport) + { + onBossAllyDeath?.Invoke(damageReport); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/BaseConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/BaseConVar.cs new file mode 100644 index 0000000..05d78ad --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/BaseConVar.cs @@ -0,0 +1,127 @@ +using System; +using System.Text; +using HG; +using UnityEngine; + +namespace RoR2.ConVar; + +public abstract class BaseConVar +{ + public string name; + + public ConVarFlags flags; + + public string defaultValue; + + public string helpText; + + protected BaseConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + this.name = name; + this.flags = flags; + this.defaultValue = defaultValue; + if (helpText == null) + { + throw new ArgumentNullException("helpText"); + } + this.helpText = helpText; + } + + public void AttemptSetString(string newValue) + { + try + { + SetString(newValue); + } + catch (ConCommandException ex) + { + Debug.LogFormat("Could not set value of ConVar \"{0}\" to \"{1}\": {2}", name, newValue, ex.Message); + } + } + + public abstract void SetString(string newValue); + + public abstract string GetString(); + + protected static void GetEnumValue(string str, ref T dest) where T : struct, Enum + { + if (Enum.TryParse(str, out var result)) + { + dest = result; + return; + } + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + stringBuilder.Append("Provided value \"").Append(str).Append("\"") + .Append(" is not a recognized option. Recognized options: { "); + bool flag = false; + string[] names = Enum.GetNames(typeof(T)); + foreach (string value in names) + { + if (flag) + { + stringBuilder.Append(", "); + } + else + { + flag = true; + } + stringBuilder.Append("\"").Append(value).Append("\""); + } + stringBuilder.Append(" }"); + string message = stringBuilder.ToString(); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + throw new ConCommandException(message); + } + + protected static int ParseIntInvariant(string str) + { + if (TextSerialization.TryParseInvariant(str, out int result)) + { + return result; + } + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + stringBuilder.Append("Provided value \"").Append(str).Append("\"") + .Append(" is not a valid number."); + string message = stringBuilder.ToString(); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + throw new ConCommandException(message); + } + + protected static float ParseFloatInvariant(string str) + { + if (TextSerialization.TryParseInvariant(str, out float result)) + { + return result; + } + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + stringBuilder.Append("Provided value \"").Append(str).Append("\"") + .Append(" is not a valid number."); + string message = stringBuilder.ToString(); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + throw new ConCommandException(message); + } + + protected static bool ParseBoolInvariant(string str) + { + if (TextSerialization.TryParseInvariant(str, out int result)) + { + switch (result) + { + case 0: + return false; + case 1: + return true; + } + } + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + stringBuilder.Append("Provided value \"").Append(str).Append("\"") + .Append(" was neither \"0\" nor \"1\"."); + string message = stringBuilder.ToString(); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + throw new ConCommandException(message); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/BoolConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/BoolConVar.cs new file mode 100644 index 0000000..308385a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/BoolConVar.cs @@ -0,0 +1,33 @@ +namespace RoR2.ConVar; + +public class BoolConVar : BaseConVar +{ + public bool value { get; protected set; } + + public BoolConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public void SetBool(bool newValue) + { + value = newValue; + } + + public override void SetString(string newValue) + { + if (TextSerialization.TryParseInvariant(newValue, out int result)) + { + value = result != 0; + } + } + + public override string GetString() + { + if (!value) + { + return "0"; + } + return "1"; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/FloatConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/FloatConVar.cs new file mode 100644 index 0000000..b4e622e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/FloatConVar.cs @@ -0,0 +1,24 @@ +namespace RoR2.ConVar; + +public class FloatConVar : BaseConVar +{ + public float value { get; protected set; } + + public FloatConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (TextSerialization.TryParseInvariant(newValue, out float result) && !float.IsNaN(result) && !float.IsInfinity(result)) + { + value = result; + } + } + + public override string GetString() + { + return TextSerialization.ToStringInvariant(value); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/IntConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/IntConVar.cs new file mode 100644 index 0000000..171ed8e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/IntConVar.cs @@ -0,0 +1,24 @@ +namespace RoR2.ConVar; + +public class IntConVar : BaseConVar +{ + public int value { get; protected set; } + + public IntConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (TextSerialization.TryParseInvariant(newValue, out int result)) + { + value = result; + } + } + + public override string GetString() + { + return TextSerialization.ToStringInvariant(value); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/PlayerPrefsIntConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/PlayerPrefsIntConVar.cs new file mode 100644 index 0000000..a84c5a4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/PlayerPrefsIntConVar.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace RoR2.ConVar; + +public class PlayerPrefsIntConVar : BaseConVar +{ + private int? defaultValueInt; + + public int value + { + get + { + if (!defaultValueInt.HasValue && int.TryParse(defaultValue, out var result)) + { + defaultValueInt = result; + } + if (defaultValueInt.HasValue) + { + return PlayerPrefs.GetInt(name, defaultValueInt.Value); + } + return PlayerPrefs.GetInt(name); + } + set + { + PlayerPrefs.SetInt(name, value); + PlayerPrefs.Save(); + } + } + + public PlayerPrefsIntConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (TextSerialization.TryParseInvariant(newValue, out int result)) + { + value = result; + } + } + + public override string GetString() + { + return TextSerialization.ToStringInvariant(value); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/StringConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/StringConVar.cs new file mode 100644 index 0000000..e14da42 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/StringConVar.cs @@ -0,0 +1,21 @@ +namespace RoR2.ConVar; + +public class StringConVar : BaseConVar +{ + public string value { get; protected set; } + + public StringConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + value = newValue; + } + + public override string GetString() + { + return value; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/ToggleDelegateConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/ToggleDelegateConVar.cs new file mode 100644 index 0000000..78340e2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/ToggleDelegateConVar.cs @@ -0,0 +1,27 @@ +using System; + +namespace RoR2.ConVar; + +public sealed class ToggleDelegateConVar : ToggleVirtualConVar +{ + private readonly Action onEnable; + + private readonly Action onDisable; + + public ToggleDelegateConVar(string name, ConVarFlags flags, string defaultValue, string helpText, Action onEnable, Action onDisable) + : base(name, flags, defaultValue, helpText) + { + this.onEnable = onEnable; + this.onDisable = onDisable; + } + + protected override void OnEnable() + { + onEnable?.Invoke(); + } + + protected override void OnDisable() + { + onDisable?.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ConVar/ToggleVirtualConVar.cs b/ilspy_dump/ror2_csproj/RoR2.ConVar/ToggleVirtualConVar.cs new file mode 100644 index 0000000..cffb188 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ConVar/ToggleVirtualConVar.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; + +namespace RoR2.ConVar; + +public abstract class ToggleVirtualConVar : BaseConVar +{ + private bool _enabled; + + private static readonly List enabledInstances; + + public bool enabled + { + get + { + return _enabled; + } + protected set + { + if (_enabled != value) + { + _enabled = value; + if (_enabled) + { + enabledInstances.Add(this); + OnEnable(); + } + else + { + enabledInstances.Remove(this); + OnDisable(); + } + } + } + } + + public bool value => enabled; + + static ToggleVirtualConVar() + { + enabledInstances = new List(); + RoR2Application.onShutDown = (Action)Delegate.Combine(RoR2Application.onShutDown, new Action(OnApplicationShutDown)); + } + + public ToggleVirtualConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + protected abstract void OnEnable(); + + protected abstract void OnDisable(); + + public override void SetString(string newValue) + { + enabled = BaseConVar.ParseBoolInvariant(newValue); + } + + public override string GetString() + { + if (!enabled) + { + return "0"; + } + return "1"; + } + + private static void OnApplicationShutDown() + { + while (enabledInstances.Count > 0) + { + enabledInstances[enabledInstances.Count - 1].enabled = false; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesDirectory.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesDirectory.cs new file mode 100644 index 0000000..dd46e21 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesDirectory.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using HG; +using HG.AssetManagement; +using HG.AsyncOperations; +using UnityEngine; +using UnityEngine.AddressableAssets; +using UnityEngine.AddressableAssets.ResourceLocators; +using UnityEngine.ResourceManagement.AsyncOperations; +using UnityEngine.ResourceManagement.ResourceLocations; + +namespace RoR2.ContentManagement; + +public class AddressablesDirectory : IAssetRepository +{ + public class AddressablesLoadAsyncOperationWrapper : BaseAsyncOperation where TAsset : UnityEngine.Object + { + private AsyncOperationHandle[] handles; + + private int completionCount; + + private List results = new List(); + + public override float progress + { + get + { + float num = 0f; + if (handles.Length == 0) + { + return 0f; + } + float num2 = 1f / (float)handles.Length; + for (int i = 0; i < handles.Length; i++) + { + num += handles[i].PercentComplete * num2; + } + return num; + } + } + + public AddressablesLoadAsyncOperationWrapper(IReadOnlyList> handles) + { + if (handles.Count == 0) + { + this.handles = Array.Empty>(); + Complete(Array.Empty()); + return; + } + results = new List(handles.Count); + this.handles = new AsyncOperationHandle[handles.Count]; + Action> value = OnChildOperationCompleted; + for (int i = 0; i < handles.Count; i++) + { + this.handles[i] = handles[i]; + AsyncOperationHandle asyncOperationHandle = handles[i]; + asyncOperationHandle.Completed += value; + } + } + + private void OnChildOperationCompleted(AsyncOperationHandle handle) + { + if ((bool)handle.Result) + { + results.Add(handle.Result); + } + completionCount++; + if (completionCount == handles.Length) + { + Complete(results.ToArray()); + } + } + } + + private string baseDirectory; + + private FilePathTree folderTree; + + private IResourceLocator[] resourceLocators = Array.Empty(); + + public AddressablesDirectory(string baseDirectory, IEnumerable resourceLocators) + { + baseDirectory = baseDirectory ?? string.Empty; + if (baseDirectory.Length > 0 && !baseDirectory.EndsWith("/")) + { + throw new ArgumentException("'baseDirectory' must be empty or end with '/'. baseDirectory=\"" + baseDirectory + "\""); + } + this.baseDirectory = baseDirectory; + this.resourceLocators = resourceLocators.ToArray(); + List list = new List(); + IResourceLocator[] array = this.resourceLocators; + for (int i = 0; i < array.Length; i++) + { + foreach (object key in array[i].Keys) + { + if (key is string text && text.StartsWith(baseDirectory)) + { + list.Add(text); + } + } + } + folderTree = FilePathTree.Create(list); + } + + public BaseAsyncOperation LoadAllAsync(string folderPath) where TAsset : UnityEngine.Object + { + List list = new List(); + string folderPath2 = baseDirectory + folderPath; + folderTree.GetEntriesInFolder(folderPath2, list); + _ = list.Count; + return IssueLoadOperationAsGroup(list); + } + + private BaseAsyncOperation IssueLoadOperationAsGroup(List entriesToLoad) where TAsset : UnityEngine.Object + { + List locations = FilterPathsByType(entriesToLoad); + List results = new List(); + AsyncOperationHandle> loadOperationHandle = Addressables.LoadAssetsAsync(locations, delegate(TAsset result) + { + results.Add(result); + }); + ScriptedAsyncOperation resultOperation = new ScriptedAsyncOperation(() => loadOperationHandle.PercentComplete); + loadOperationHandle.Completed += delegate + { + resultOperation.Complete(results.ToArray()); + }; + return resultOperation; + } + + private BaseAsyncOperation IssueLoadOperationsIndividually(List entriesToLoad) where TAsset : UnityEngine.Object + { + List list = FilterPathsByType(entriesToLoad); + AsyncOperationHandle[] array = new AsyncOperationHandle[list.Count]; + for (int i = 0; i < list.Count; i++) + { + AsyncOperationHandle asyncOperationHandle = Addressables.LoadAssetAsync(list[i]); + array[i] = asyncOperationHandle; + } + return new AddressablesLoadAsyncOperationWrapper(array); + } + + private List FilterPathsByType(List paths) + { + Type typeFromHandle = typeof(TAsset); + bool[] array = new bool[paths.Count]; + List list = new List(); + IResourceLocator[] array2 = resourceLocators; + foreach (IResourceLocator resourceLocator in array2) + { + for (int j = 0; j < paths.Count; j++) + { + if (array[j] || !resourceLocator.Locate(paths[j], null, out var locations)) + { + continue; + } + for (int k = 0; k < locations.Count; k++) + { + IResourceLocation resourceLocation = locations[k]; + if (typeFromHandle.IsAssignableFrom(resourceLocation.ResourceType)) + { + list.Add(resourceLocation); + array[j] = true; + break; + } + } + } + } + return list; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesLabels.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesLabels.cs new file mode 100644 index 0000000..77f863d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesLabels.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Projectile; +using RoR2.Skills; +using UnityEngine.Networking; + +namespace RoR2.ContentManagement; + +public static class AddressablesLabels +{ + public static readonly string characterBody = "CharacterBody"; + + public static readonly string characterMaster = "CharacterMaster"; + + public static readonly string projectile = "Projectile"; + + public static readonly string gameMode = "GameMode"; + + public static readonly string networkedObject = "NetworkedObject"; + + public static readonly string effect = "Effect"; + + public static readonly string skillFamily = "SkillFamily"; + + public static readonly string skillDef = "SkillDef"; + + public static readonly string unlockableDef = "UnlockableDef"; + + public static readonly string surfaceDef = "SurfaceDef"; + + public static readonly string sceneDef = "SceneDef"; + + public static readonly string networkSoundEventDef = "NetworkSoundEventDef"; + + public static readonly string musicTrackDef = "MusicTrackDef"; + + public static readonly string gameEndingDef = "GameEndingDef"; + + public static readonly string itemDef = "ItemDef"; + + public static readonly string itemTierDef = "ItemTierDef"; + + public static readonly string equipmentDef = "EquipmentDef"; + + public static readonly string buffDef = "BuffDef"; + + public static readonly string eliteDef = "EliteDef"; + + public static readonly string survivorDef = "SurvivorDef"; + + public static readonly string artifactDef = "ArtifactDef"; + + public static readonly string entityStateConfiguration = "EntityStateConfiguration"; + + public static readonly string expansionDef = "ExpansionDef"; + + public static readonly string entitlementDef = "EntitlementDef"; + + public static readonly string itemRelationshipType = "ItemRelationshipType"; + + public static readonly string itemRelationshipProvider = "ItemRelationshipProvider"; + + public static readonly string miscPickupDef = "MiscPickupDef"; + + public static readonly IReadOnlyDictionary componentTypeLabels = new Dictionary + { + [typeof(CharacterBody)] = characterBody, + [typeof(CharacterMaster)] = characterMaster, + [typeof(ProjectileController)] = projectile, + [typeof(Run)] = gameMode, + [typeof(NetworkIdentity)] = networkedObject, + [typeof(EffectComponent)] = effect + }; + + public static readonly IReadOnlyDictionary assetTypeLabels = new Dictionary + { + [typeof(SkillFamily)] = skillFamily, + [typeof(SkillDef)] = skillDef, + [typeof(UnlockableDef)] = unlockableDef, + [typeof(SurfaceDef)] = surfaceDef, + [typeof(SceneDef)] = sceneDef, + [typeof(NetworkSoundEventDef)] = networkSoundEventDef, + [typeof(MusicTrackDef)] = musicTrackDef, + [typeof(GameEndingDef)] = gameEndingDef, + [typeof(ItemDef)] = itemDef, + [typeof(ItemTierDef)] = itemTierDef, + [typeof(EquipmentDef)] = equipmentDef, + [typeof(BuffDef)] = buffDef, + [typeof(EliteDef)] = eliteDef, + [typeof(SurvivorDef)] = survivorDef, + [typeof(ArtifactDef)] = artifactDef, + [typeof(EntityStateConfiguration)] = entityStateConfiguration, + [typeof(ExpansionDef)] = expansionDef, + [typeof(EntitlementDef)] = entitlementDef, + [typeof(ItemRelationshipProvider)] = itemRelationshipProvider, + [typeof(ItemRelationshipType)] = itemRelationshipType, + [typeof(MiscPickupDef)] = miscPickupDef + }; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesLoadHelper.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesLoadHelper.cs new file mode 100644 index 0000000..100e79d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/AddressablesLoadHelper.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using HG; +using HG.AsyncOperations; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Skills; +using UnityEngine; +using UnityEngine.AddressableAssets; +using UnityEngine.AddressableAssets.ResourceLocators; +using UnityEngine.ResourceManagement; +using UnityEngine.ResourceManagement.AsyncOperations; +using UnityEngine.ResourceManagement.ResourceLocations; + +namespace RoR2.ContentManagement; + +public class AddressablesLoadHelper +{ + private class Operation + { + public float weight; + + public IEnumerator coroutine; + + public float progress; + } + + public class AddressablesLoadAsyncOperationWrapper : BaseAsyncOperation where TAsset : UnityEngine.Object + { + private AsyncOperationHandle>[] handles; + + private int completionCount; + + public override float progress => 0f; + + public AddressablesLoadAsyncOperationWrapper(IReadOnlyList>> handles) + { + if (handles.Count == 0) + { + this.handles = Array.Empty>>(); + Complete(Array.Empty()); + return; + } + Action>> value = OnChildOperationCompleted; + this.handles = new AsyncOperationHandle>[handles.Count]; + for (int i = 0; i < handles.Count; i++) + { + this.handles[i] = handles[i]; + AsyncOperationHandle> asyncOperationHandle = handles[i]; + asyncOperationHandle.Completed += value; + } + } + + private void OnChildOperationCompleted(AsyncOperationHandle> completedOperationHandle) + { + completionCount++; + if (completionCount != handles.Length) + { + return; + } + List list = new List(); + AsyncOperationHandle>[] array = handles; + for (int i = 0; i < array.Length; i++) + { + AsyncOperationHandle> asyncOperationHandle = array[i]; + if (asyncOperationHandle.Result != null) + { + list.AddRange(asyncOperationHandle.Result); + } + } + Complete(list.ToArray()); + } + } + + private readonly IResourceLocator[] resourceLocators = Array.Empty(); + + private readonly object[] requiredKeys = Array.Empty(); + + public int maxConcurrentOperations = 2; + + public float timeoutDuration = float.PositiveInfinity; + + private const int loadOperationsStartedMax = 28; + + private int loadOperationsStartedCount; + + private readonly List allOperations = new List(); + + private readonly Queue pendingLoadOperations = new Queue(); + + private readonly List runningLoadOperations = new List(); + + private readonly List allGenericOperations = new List(); + + public ReadableProgress progress { get; private set; } + + public IEnumerator coroutine { get; private set; } + + private float loadOperationsStartedProgress01 => Mathf.Clamp01((float)loadOperationsStartedCount / 28f); + + public AddressablesLoadHelper(IReadOnlyList resourceLocators, object[] requiredKeys = null) + { + ArrayUtils.CloneTo(resourceLocators, ref this.resourceLocators); + if (requiredKeys != null) + { + ArrayUtils.CloneTo(requiredKeys, ref this.requiredKeys); + } + progress = new ReadableProgress(); + coroutine = Coroutine(progress); + } + + public AddressablesLoadHelper(IResourceLocator resourceLocator, object[] requiredKeys = null) + : this(new IResourceLocator[1] { resourceLocator }, requiredKeys) + { + } + + public static AddressablesLoadHelper CreateUsingDefaultResourceLocator(object[] requiredKeys = null) + { + return new AddressablesLoadHelper(Addressables.ResourceLocators.First(), requiredKeys); + } + + public static AddressablesLoadHelper CreateUsingDefaultResourceLocator(object requiredKey) + { + return CreateUsingDefaultResourceLocator(new object[1] { requiredKey }); + } + + public IEnumerator AddContentPackLoadOperationWithYields(ContentPack contentPack) + { + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.characterBody, contentPack.bodyPrefabs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.characterMaster, contentPack.masterPrefabs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.projectile, contentPack.projectilePrefabs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.gameMode, contentPack.gameModePrefabs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.networkedObject, contentPack.networkedObjectPrefabs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.skillFamily, contentPack.skillFamilies.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.skillDef, contentPack.skillDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.unlockableDef, contentPack.unlockableDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.surfaceDef, contentPack.surfaceDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.sceneDef, contentPack.sceneDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.networkSoundEventDef, contentPack.networkSoundEventDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.musicTrackDef, contentPack.musicTrackDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.gameEndingDef, contentPack.gameEndingDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.itemDef, contentPack.itemDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.itemTierDef, contentPack.itemTierDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.itemRelationshipProvider, contentPack.itemRelationshipProviders.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.itemRelationshipType, contentPack.itemRelationshipTypes.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.equipmentDef, contentPack.equipmentDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.miscPickupDef, contentPack.miscPickupDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.buffDef, contentPack.buffDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.eliteDef, contentPack.eliteDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.survivorDef, contentPack.survivorDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.artifactDef, contentPack.artifactDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.effect, contentPack.effectDefs.Add, (GameObject asset) => new EffectDef(asset)); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.entityStateConfiguration, contentPack.entityStateConfigurations.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.expansionDef, contentPack.expansionDefs.Add); + yield return FindLocationsThenAddLoadOperation(AddressablesLabels.entitlementDef, contentPack.entitlementDefs.Add); + loadOperationsStartedCount = 28; + AddGenericOperation(AddEntityStateTypes(), 0.05f); + yield return null; + IEnumerator AddEntityStateTypes() + { + contentPack.entityStateTypes.Add((from v in contentPack.entityStateConfigurations + select (Type)v.targetType into v + where v != null + select v).ToArray()); + yield return null; + } + } + + public IEnumerator FindLocationsThenAddLoadOperation(string key, Action onComplete, float weight = 1f) where TAssetSrc : UnityEngine.Object + { + return FindLocationsThenAddLoadOperation(key, onComplete, null, weight); + } + + public IEnumerator FindLocationsThenAddLoadOperation(string key, Action onComplete, Func selector = null, float weight = 1f) where TAssetSrc : UnityEngine.Object + { + List list = new List(); + ListUtils.AddRange(list, requiredKeys); + list.Add(key); + AsyncOperationHandle> locationAsyncOperationHandle = Addressables.LoadResourceLocationsAsync((IEnumerable)list, Addressables.MergeMode.Intersection, (Type)null); + while (!locationAsyncOperationHandle.IsDone) + { + yield return null; + } + IList result = locationAsyncOperationHandle.Result; + AddLoadOperation(result, onComplete, selector, weight); + loadOperationsStartedCount++; + } + + public void AddLoadOperation(IList locations, Action onComplete, float weight = 1f) where TAssetSrc : UnityEngine.Object + { + AddLoadOperation(locations, onComplete, null, weight); + } + + public void AddLoadOperation(IList locations, Action onComplete, Func selector = null, float weight = 1f) where TAssetSrc : UnityEngine.Object + { + Operation loadOperation = new Operation + { + weight = weight + }; + loadOperation.coroutine = Coroutine(); + allOperations.Add(loadOperation); + pendingLoadOperations.Enqueue(loadOperation); + IEnumerator Coroutine() + { + yield return null; + List>> underlyingLoadOperations = new List>>(resourceLocators.Length); + int j = 0; + while (j < resourceLocators.Length) + { + Action oldResourceManagerExceptionHandler = ResourceManager.ExceptionHandler; + ResourceManager.ExceptionHandler = ResourceManagerExceptionHandler; + try + { + List locationsList = locations as List; + int sliceStart = 0; + int arrayLength = locations.Count; + do + { + int count = Mathf.Min(5, arrayLength - sliceStart); + AsyncOperationHandle> item = Addressables.LoadAssetsAsync(locationsList.GetRange(sliceStart, count), null); + underlyingLoadOperations.Add(item); + sliceStart += 5; + yield return null; + } + while (sliceStart < arrayLength); + Addressables.Release(locations); + } + finally + { + ResourceManager.ExceptionHandler = oldResourceManagerExceptionHandler; + } + int num = j + 1; + j = num; + void ResourceManagerExceptionHandler(AsyncOperationHandle operationHandle, Exception exception) + { + if (!(exception is InvalidKeyException)) + { + oldResourceManagerExceptionHandler?.Invoke(operationHandle, exception); + } + } + } + AddressablesLoadAsyncOperationWrapper combinedLoadOperation = new AddressablesLoadAsyncOperationWrapper(underlyingLoadOperations); + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + while (!combinedLoadOperation.isDone) + { + loadOperation.progress = combinedLoadOperation.progress; + float num2 = (float)stopwatch.Elapsed.TotalSeconds; + if (num2 > timeoutDuration) + { + throw new Exception($"Loading exceeded timeout. elapsedSeconds={num2} timeoutDuration={timeoutDuration}"); + } + yield return null; + } + TAssetSrc[] loadedAssets = combinedLoadOperation.result.Where((TAssetSrc asset) => asset).ToArray(); + loadOperation.progress = 0.97f; + yield return null; + if (onComplete != null) + { + TAssetDest[] convertedAssets; + if (selector == null) + { + if (!(typeof(TAssetSrc) == typeof(TAssetDest))) + { + throw new ArgumentNullException("selector", "Converter must be provided when TAssetSrc and TAssetDest differ."); + } + convertedAssets = (TAssetDest[])(object)loadedAssets; + } + else + { + convertedAssets = new TAssetDest[loadedAssets.Length]; + j = 0; + while (j < loadedAssets.Length) + { + yield return null; + convertedAssets[j] = selector(loadedAssets[j]); + int num = j + 1; + j = num; + } + } + yield return null; + string[] assetNames = new string[loadedAssets.Length]; + for (int k = 0; k < loadedAssets.Length; k++) + { + assetNames[k] = loadedAssets[k].name; + } + yield return null; + Array.Sort(assetNames, convertedAssets, StringComparer.Ordinal); + onComplete?.Invoke(convertedAssets); + } + loadOperation.progress = 1f; + } + } + + public void AddGenericOperation(IEnumerator coroutine, float weight = 1f) + { + Operation item = new Operation + { + weight = weight, + coroutine = coroutine + }; + allOperations.Add(item); + allGenericOperations.Add(item); + } + + public void AddGenericOperation(IEnumerable coroutineProvider, float weight = 1f) + { + AddGenericOperation(coroutineProvider.GetEnumerator(), weight); + } + + public void AddGenericOperation(Func coroutineMethod, float weight = 1f) + { + AddGenericOperation(coroutineMethod(), weight); + } + + public void AddGenericOperation(Action action, float weight = 1f) + { + AddGenericOperation(Coroutine(), weight); + IEnumerator Coroutine() + { + action(); + yield return null; + } + } + + private IEnumerator Coroutine(IProgress progressReceiver) + { + while (pendingLoadOperations.Count > 0 || runningLoadOperations.Count > 0) + { + while (pendingLoadOperations.Count > 0 && runningLoadOperations.Count < maxConcurrentOperations) + { + runningLoadOperations.Add(pendingLoadOperations.Dequeue()); + } + int i = 0; + while (i < runningLoadOperations.Count) + { + Operation operation = runningLoadOperations[i]; + int num; + if (operation.coroutine.MoveNext()) + { + UpdateProgress(); + yield return operation.coroutine.Current; + } + else + { + runningLoadOperations.RemoveAt(i); + num = i - 1; + i = num; + } + num = i + 1; + i = num; + } + } + foreach (Operation genericOperation in allGenericOperations) + { + while (genericOperation.coroutine.MoveNext()) + { + UpdateProgress(); + yield return genericOperation.coroutine.Current; + } + } + progressReceiver.Report(1f); + void UpdateProgress() + { + float num2 = 0f; + float num3 = 0f; + for (int j = 0; j < allOperations.Count; j++) + { + Operation operation2 = allOperations[j]; + num2 += operation2.weight; + num3 += operation2.progress * operation2.weight; + } + if (num2 == 0f) + { + num2 = 1f; + num3 = 0.5f; + } + float num4 = loadOperationsStartedProgress01; + float num5 = num3 / num2; + progressReceiver.Report(num4 * 0.25f + num5 * 0.75f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentAssetRefResolver.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentAssetRefResolver.cs new file mode 100644 index 0000000..46cd367 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentAssetRefResolver.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using HG; +using UnityEngine; + +namespace RoR2.ContentManagement; + +[CreateAssetMenu(menuName = "RoR2/ContentAssetRefResolver")] +public class ContentAssetRefResolver : ScriptableObject +{ + [Serializable] + public struct FieldAssignmentInfo + { + public UnityEngine.Object targetObject; + + public string fieldPath; + + public ContentAssetPath contentAssetPath; + } + + [Serializable] + public struct ContentAssetPath + { + public string contentPackIdentifier; + + public string collectionName; + + public string assetName; + } + + public bool applyOnEnable = true; + + public FieldAssignmentInfo[] fieldAssignmentInfos; + + private static bool contentPacksLoaded; + + private static Queue pendingResolutions; + + private static ReadOnlyArray loadedContentPacks; + + [ContextMenu("Run Test")] + public void Apply() + { + for (int i = 0; i < fieldAssignmentInfos.Length; i++) + { + ApplyFieldAssignmentInfo(in fieldAssignmentInfos[i]); + } + } + + private object FindContentAsset(in ContentAssetPath contentAssetPath) + { + for (int i = 0; i < loadedContentPacks.Length; i++) + { + if (loadedContentPacks[i].identifier.Equals(contentAssetPath.contentPackIdentifier, StringComparison.Ordinal)) + { + ReadOnlyContentPack readOnlyContentPack = loadedContentPacks[i]; + readOnlyContentPack.FindAsset(contentAssetPath.collectionName, contentAssetPath.assetName, out var result); + return result; + } + } + return null; + } + + static ContentAssetRefResolver() + { + contentPacksLoaded = false; + pendingResolutions = new Queue(); + loadedContentPacks = Array.Empty(); + ContentManager.onContentPacksAssigned += OnContentPacksLoaded; + } + + private static void OnContentPacksLoaded(ReadOnlyArray newLoadedContentPacks) + { + loadedContentPacks = newLoadedContentPacks; + contentPacksLoaded = true; + ApplyQueued(); + } + + private static void ApplyQueued() + { + while (pendingResolutions.Count > 0) + { + ContentAssetRefResolver contentAssetRefResolver = pendingResolutions.Dequeue(); + try + { + contentAssetRefResolver.Apply(); + } + catch (Exception message) + { + Debug.LogError(message); + } + } + } + + private void OnEnable() + { + if (applyOnEnable) + { + if (contentPacksLoaded) + { + Apply(); + } + else + { + pendingResolutions.Enqueue(this); + } + } + } + + private bool ApplyFieldAssignmentInfo(in FieldAssignmentInfo fieldAssignmentInfo) + { + object obj2 = fieldAssignmentInfo.targetObject; + string fieldPath = fieldAssignmentInfo.fieldPath; + UnityEngine.Object valueToAssign = FindContentAsset(in fieldAssignmentInfo.contentAssetPath) as UnityEngine.Object; + int currentReadPos = 0; + try + { + if (obj2 == null) + { + throw new NullReferenceException("targetObject is null"); + } + ProcessObject(ref obj2); + return true; + } + catch (Exception ex) + { + Debug.LogError($"Could not assign {obj2}.{fieldPath}={valueToAssign}: {ex}"); + return false; + } + void HandleInnerValue(ref object innerValue) + { + if (currentReadPos < fieldPath.Length) + { + if (innerValue == null) + { + throw new Exception(fieldPath.Substring(0, currentReadPos) + " is null."); + } + if (innerValue is UnityEngine.Object) + { + throw new Exception("Assignment cannot propagate through UnityEngine.Object."); + } + ProcessObject(ref innerValue); + } + else + { + innerValue = valueToAssign; + } + } + static bool IsIdentifierChar(char c) + { + if (!char.IsLetterOrDigit(c)) + { + return c == '_'; + } + return true; + } + void ProcessObject(ref object obj) + { + Type type = obj.GetType(); + if (obj is IList list) + { + int index = TakeArrayIndex(); + object innerValue2 = list[index]; + HandleInnerValue(ref innerValue2); + list[index] = innerValue2; + } + else + { + string text2 = TakeIdentifier(); + FieldInfo field = type.GetField(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + if (field == null) + { + throw new Exception("Field \"" + type.Name + "." + text2 + "\" could not be found."); + } + object innerValue3 = field.GetValue(obj); + HandleInnerValue(ref innerValue3); + field.SetValue(obj, innerValue3); + } + } + int TakeArrayIndex() + { + char c4 = fieldPath[currentReadPos]; + if (c4 != '[') + { + throw new FormatException($"Expected char '[' but got '{c4}'."); + } + int num5 = currentReadPos + 1; + currentReadPos = num5; + int num6 = TakeInt(); + if (num6 < 0) + { + throw new FormatException($"Array index {num6} cannot be negative."); + } + char c5 = fieldPath[currentReadPos]; + if (c5 != ']') + { + throw new FormatException($"Expected char ']' but got '{c5}'."); + } + num5 = currentReadPos + 1; + currentReadPos = num5; + return num6; + } + string TakeIdentifier() + { + int num = currentReadPos; + string text = null; + char c2 = fieldPath[currentReadPos]; + if (c2 == '.') + { + num++; + int num2 = currentReadPos + 1; + currentReadPos = num2; + } + else if (currentReadPos != 0) + { + throw new Exception($"Expected '.' at {num}, but encountered '{c2}'"); + } + while (currentReadPos < fieldPath.Length && IsIdentifierChar(fieldPath[currentReadPos])) + { + int num2 = currentReadPos + 1; + currentReadPos = num2; + } + text = fieldPath.Substring(num, currentReadPos - num); + if (text == null) + { + throw new FormatException($"Expected identifier at {num}, but encountered end of string."); + } + if (text.Length == 0) + { + throw new FormatException($"Expected identifier at {num}, but encountered no valid characters (a-zA-Z0-9_)."); + } + if (char.IsDigit(text[0])) + { + throw new FormatException($"Expected identifier at {num}, but an identifier cannot begin with a digit. digit={text[0]} substring={text}"); + } + return text; + } + int TakeInt() + { + int num3 = currentReadPos; + if (num3 >= fieldPath.Length) + { + throw new FormatException($"Expected integer at {num3}, but encountered end of string."); + } + char c3 = fieldPath[currentReadPos]; + if (c3 != '-' && !char.IsDigit(c3)) + { + throw new FormatException($"Expected integer at {num3}, but an integer cannot begin with character '{c3}'"); + } + if (c3 == '-') + { + int num4 = currentReadPos + 1; + currentReadPos = num4; + } + while (currentReadPos < fieldPath.Length) + { + if (!char.IsDigit(fieldPath[currentReadPos]) || currentReadPos == fieldPath.Length - 1) + { + fieldPath.Substring(num3, currentReadPos + 1 - num3); + break; + } + int num4 = currentReadPos + 1; + currentReadPos = num4; + } + string obj3 = fieldPath.Substring(num3, currentReadPos - num3) ?? throw new FormatException($"Expected integer at {num3}, but encountered end of string."); + if (obj3.Length == 0) + { + throw new FormatException($"Expected integer at {num3}, but encountered no valid characters (-0-9)."); + } + return int.Parse(obj3); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentLoadHelper.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentLoadHelper.cs new file mode 100644 index 0000000..3ee8ec3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentLoadHelper.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections; +using System.Linq; +using System.Reflection; +using HG; +using HG.AssetManagement; +using HG.AsyncOperations; +using HG.Coroutines; +using UnityEngine; + +namespace RoR2.ContentManagement; + +public class ContentLoadHelper +{ + public delegate ref T GetRefDelegate(); + + public delegate void AcceptResultDelegate(T result); + + public IAssetRepository assetRepository; + + public ReadableProgress progress; + + public ParallelProgressCoroutine coroutine; + + public ContentLoadHelper() + { + progress = new ReadableProgress(); + coroutine = new ParallelProgressCoroutine(progress); + } + + public void DispatchLoadConvert(string folderPath, Action onComplete, Func selector = null) where TAssetSrc : UnityEngine.Object + { + ReadableProgress progressReceiver = new ReadableProgress(); + coroutine.Add(Coroutine(), progressReceiver); + IEnumerator Coroutine() + { + BaseAsyncOperation loadFolderOperation = assetRepository.LoadAllAsync(folderPath); + while (!loadFolderOperation.isDone) + { + progressReceiver.Report(Util.Remap(progressReceiver.value, 0f, 1f, 0f, 0.95f)); + yield return null; + } + TAssetSrc[] loadedAssets = loadFolderOperation.result.Where((TAssetSrc asset) => asset).ToArray(); + progressReceiver.Report(0.97f); + yield return null; + if (onComplete != null) + { + TAssetDest[] convertedAssets; + if (selector == null) + { + if (!(typeof(TAssetSrc) == typeof(TAssetDest))) + { + throw new ArgumentNullException("selector", "Converter must be provided when TAssetSrc and TAssetDest differ."); + } + convertedAssets = (TAssetDest[])(object)loadedAssets; + } + else + { + convertedAssets = new TAssetDest[loadedAssets.Length]; + int i = 0; + while (i < loadedAssets.Length) + { + yield return null; + convertedAssets[i] = selector(loadedAssets[i]); + int num = i + 1; + i = num; + } + } + yield return null; + string[] assetNames = new string[loadedAssets.Length]; + for (int j = 0; j < loadedAssets.Length; j++) + { + assetNames[j] = loadedAssets[j].name; + } + yield return null; + Array.Sort(assetNames, convertedAssets, StringComparer.Ordinal); + onComplete?.Invoke(convertedAssets); + } + progressReceiver.Report(1f); + } + } + + public void DispatchLoad(string folderPath, Action onComplete) where TAsset : UnityEngine.Object + { + DispatchLoadConvert(folderPath, onComplete); + } + + public static void PopulateTypeFields(Type typeToPopulate, NamedAssetCollection assets, Func fieldNameToAssetNameConverter = null) where TAsset : UnityEngine.Object + { + string[] array = new string[assets.Length]; + for (int i = 0; i < assets.Length; i++) + { + array[i] = assets.GetAssetName(assets[i]); + } + FieldInfo[] fields = typeToPopulate.GetFields(BindingFlags.Static | BindingFlags.Public); + foreach (FieldInfo fieldInfo in fields) + { + if (fieldInfo.FieldType == typeof(TAsset)) + { + TargetAssetNameAttribute customAttribute = CustomAttributeExtensions.GetCustomAttribute(fieldInfo); + string text = ((customAttribute != null) ? customAttribute.targetAssetName : ((fieldNameToAssetNameConverter == null) ? fieldInfo.Name : fieldNameToAssetNameConverter(fieldInfo.Name))); + TAsset val = assets.Find(text); + if ((object)val != null) + { + fieldInfo.SetValue(null, val); + continue; + } + Debug.LogWarning("Failed to assign " + fieldInfo.DeclaringType.Name + "." + fieldInfo.Name + ": Asset \"" + text + "\" not found."); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentManager.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentManager.cs new file mode 100644 index 0000000..91f99fa --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentManager.cs @@ -0,0 +1,352 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using HG; +using HG.Coroutines; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Skills; +using UnityEngine; + +namespace RoR2.ContentManagement; + +public static class ContentManager +{ + private class ContentPackLoader + { + private delegate IEnumerator PerContentPackAction(ref ContentPackLoadInfo contentPackLoadInfo, ReadOnlyArray readOnlyPeers, IProgress progressReceiver); + + private ContentPackLoadInfo[] contentPackLoadInfos; + + public List output = new List(); + + public ContentPackLoader(List contentPackProviders) + { + contentPackLoadInfos = new ContentPackLoadInfo[contentPackProviders.Count]; + for (int i = 0; i < contentPackProviders.Count; i++) + { + string identifier = contentPackProviders[i].identifier; + contentPackLoadInfos[i] = new ContentPackLoadInfo + { + index = i, + contentPackProviderIdentifier = identifier, + contentPackProvider = contentPackProviders[i], + previousContentPack = new ContentPack + { + identifier = identifier + }, + retries = 0 + }; + } + } + + private IEnumerator DoPerContentPackProviderCoroutine(IProgress progressReceiver, PerContentPackAction action) + { + ReadOnlyArray readOnlyPeers = ArrayUtils.Clone(contentPackLoadInfos); + ParallelProgressCoroutine parallelProgressCoroutine = new ParallelProgressCoroutine(progressReceiver); + for (int i = 0; i < contentPackLoadInfos.Length; i++) + { + ReadableProgress readableProgress = new ReadableProgress(); + IEnumerator coroutine = action(ref contentPackLoadInfos[i], readOnlyPeers, readableProgress); + parallelProgressCoroutine.Add(coroutine, readableProgress); + } + return parallelProgressCoroutine; + } + + public IEnumerator InitialLoad(IProgress progressReceiver) + { + yield return DoPerContentPackProviderCoroutine(progressReceiver, StartLoadCoroutine); + static IEnumerator StartLoadCoroutine(ref ContentPackLoadInfo loadInfo, ReadOnlyArray readOnlyPeers, IProgress providedProgressReceiver) + { + LoadStaticContentAsyncArgs args = new LoadStaticContentAsyncArgs(providedProgressReceiver, readOnlyPeers); + return loadInfo.contentPackProvider.LoadStaticContentAsync(args); + } + } + + public IEnumerator StepGenerateContentPacks(IProgress progressReceiver, IProgress completionReceiver, int retriesRemaining) + { + ContentPack[] newContentPacks = new ContentPack[contentPackLoadInfos.Length]; + for (int i = 0; i < newContentPacks.Length; i++) + { + newContentPacks[i] = new ContentPack + { + identifier = contentPackLoadInfos[i].contentPackProviderIdentifier + }; + } + yield return DoPerContentPackProviderCoroutine(progressReceiver, StartGeneratorCoroutine); + bool flag = true; + for (int j = 0; j < contentPackLoadInfos.Length; j++) + { + ContentPack contentPack = newContentPacks[j]; + contentPack.identifier = contentPackLoadInfos[j].contentPackProviderIdentifier; + if (!contentPackLoadInfos[j].previousContentPack.Equals(contentPack)) + { + flag = false; + contentPackLoadInfos[j].retries++; + contentPackLoadInfos[j].previousContentPack = contentPack; + } + } + if (flag) + { + completionReceiver.Report(value: true); + } + IEnumerator StartGeneratorCoroutine(ref ContentPackLoadInfo loadInfo, ReadOnlyArray readOnlyPeers, IProgress providedProgressReceiver) + { + ContentPack contentPack2 = newContentPacks[loadInfo.index]; + GetContentPackAsyncArgs args = new GetContentPackAsyncArgs(providedProgressReceiver, contentPack2, readOnlyPeers, retriesRemaining); + return loadInfo.contentPackProvider.GenerateContentPackAsync(args); + } + } + + public IEnumerator LoadContentPacks(IProgress progressReceiver) + { + int maxRetries = 10; + bool complete = false; + ReadableProgress completionReceiver = new ReadableProgress(delegate(bool result) + { + complete = result; + }); + int i = 0; + while (i < maxRetries) + { + yield return StepGenerateContentPacks(progressReceiver, completionReceiver, maxRetries - i - 1); + if (complete) + { + break; + } + int num = i + 1; + i = num; + } + for (int j = 0; j < contentPackLoadInfos.Length; j++) + { + output.Add(contentPackLoadInfos[j].previousContentPack); + } + } + + public IEnumerator RunCleanup(IProgress progressReceiver) + { + yield return DoPerContentPackProviderCoroutine(progressReceiver, StartFinalizeCoroutine); + IEnumerator StartFinalizeCoroutine(ref ContentPackLoadInfo loadInfo, ReadOnlyArray readOnlyPeers, IProgress providedProgressReceiver) + { + FinalizeAsyncArgs args = new FinalizeAsyncArgs(providedProgressReceiver, readOnlyPeers, contentPackLoadInfos[loadInfo.index].previousContentPack); + return loadInfo.contentPackProvider.FinalizeAsync(args); + } + } + } + + public delegate void AddContentPackProviderDelegate(IContentPackProvider contentPackProvider); + + public delegate void CollectContentPackProvidersDelegate(AddContentPackProviderDelegate addContentPackProvider); + + private static ContentPack[] contentPacks; + + public static ItemDef[] _itemDefs; + + public static ItemTierDef[] _itemTierDefs; + + private static ItemRelationshipProvider[] _itemRelationshipProviders; + + private static ItemRelationshipType[] _itemRelationshipTypes; + + public static EquipmentDef[] _equipmentDefs; + + public static BuffDef[] _buffDefs; + + public static EliteDef[] _eliteDefs; + + public static UnlockableDef[] _unlockableDefs; + + public static SurvivorDef[] _survivorDefs; + + public static GameObject[] _bodyPrefabs; + + public static GameObject[] _masterPrefabs; + + public static ArtifactDef[] _artifactDefs; + + public static EffectDef[] _effectDefs; + + public static SkillDef[] _skillDefs; + + public static SkillFamily[] _skillFamilies; + + public static SurfaceDef[] _surfaceDefs; + + public static SceneDef[] _sceneDefs; + + public static GameObject[] _projectilePrefabs; + + public static NetworkSoundEventDef[] _networkSoundEventDefs; + + public static MusicTrackDef[] _musicTrackDefs; + + public static GameObject[] _networkedObjectPrefabs; + + public static GameObject[] _gameModePrefabs; + + public static GameEndingDef[] _gameEndingDefs; + + public static EntityStateConfiguration[] _entityStateConfigurations; + + public static Type[] _entityStateTypes; + + public static ExpansionDef[] _expansionDefs; + + public static EntitlementDef[] _entitlementDefs; + + private static MiscPickupDef[] _miscPickupDefs; + + public static ItemDef[] itemDefs => _itemDefs; + + public static ItemTierDef[] itemTierDefs => _itemTierDefs; + + public static ItemRelationshipProvider[] itemRelationshipProviders => _itemRelationshipProviders; + + public static ItemRelationshipType[] itemRelationshipTypes => _itemRelationshipTypes; + + public static EquipmentDef[] equipmentDefs => _equipmentDefs; + + public static BuffDef[] buffDefs => _buffDefs; + + public static EliteDef[] eliteDefs => _eliteDefs; + + public static UnlockableDef[] unlockableDefs => _unlockableDefs; + + public static SurvivorDef[] survivorDefs => _survivorDefs; + + public static GameObject[] bodyPrefabs => _bodyPrefabs; + + public static GameObject[] masterPrefabs => _masterPrefabs; + + public static ArtifactDef[] artifactDefs => _artifactDefs; + + public static EffectDef[] effectDefs => _effectDefs; + + public static SkillDef[] skillDefs => _skillDefs; + + public static SkillFamily[] skillFamilies => _skillFamilies; + + public static SurfaceDef[] surfaceDefs => _surfaceDefs; + + public static SceneDef[] sceneDefs => _sceneDefs; + + public static GameObject[] projectilePrefabs => _projectilePrefabs; + + public static NetworkSoundEventDef[] networkSoundEventDefs => _networkSoundEventDefs; + + public static MusicTrackDef[] musicTrackDefs => _musicTrackDefs; + + public static GameObject[] networkedObjectPrefabs => _networkedObjectPrefabs; + + public static GameObject[] gameModePrefabs => _gameModePrefabs; + + public static GameEndingDef[] gameEndingDefs => _gameEndingDefs; + + public static EntityStateConfiguration[] entityStateConfigurations => _entityStateConfigurations; + + public static Type[] entityStateTypes => _entityStateTypes; + + public static ExpansionDef[] expansionDefs => _expansionDefs; + + public static EntitlementDef[] entitlementDefs => _entitlementDefs; + + public static MiscPickupDef[] miscPickupDefs => _miscPickupDefs; + + public static ReadOnlyArray allLoadedContentPacks { get; private set; } = Array.Empty(); + + + public static event CollectContentPackProvidersDelegate collectContentPackProviders; + + public static event Action> onContentPacksAssigned; + + public static IEnumerator LoadContentPacks(IProgress progressReceiver) + { + List contentPackProviders = new List(); + ContentManager.collectContentPackProviders?.Invoke(AddContentPackProvider); + ContentManager.collectContentPackProviders = null; + ContentPackLoader loader = new ContentPackLoader(contentPackProviders); + yield return loader.InitialLoad(new ReadableProgress(delegate(float newValue) + { + progressReceiver.Report(Util.Remap(newValue, 0f, 1f, 0f, 0.8f)); + })); + yield return loader.LoadContentPacks(new ReadableProgress(delegate(float newValue) + { + progressReceiver.Report(Util.Remap(newValue, 0f, 1f, 0.8f, 0.95f)); + })); + yield return loader.RunCleanup(new ReadableProgress(delegate(float newValue) + { + progressReceiver.Report(Util.Remap(newValue, 0f, 1f, 0.95f, 1f)); + })); + yield return SetContentPacks(loader.output); + void AddContentPackProvider(IContentPackProvider contentPackProvider) + { + contentPackProviders.Add(contentPackProvider); + } + } + + private static IEnumerator SetContentPacks(List newContentPacks) + { + allLoadedContentPacks = newContentPacks.ToArray(); + SetAssets(ref _itemDefs, (ReadOnlyContentPack contentPack) => contentPack.itemDefs); + SetAssets(ref _itemTierDefs, (ReadOnlyContentPack contentPack) => contentPack.itemTierDefs); + SetAssets(ref _itemRelationshipProviders, (ReadOnlyContentPack contentPack) => contentPack.itemRelationshipProviders); + SetAssets(ref _itemRelationshipTypes, (ReadOnlyContentPack contentPack) => contentPack.itemRelationshipTypes); + SetAssets(ref _equipmentDefs, (ReadOnlyContentPack contentPack) => contentPack.equipmentDefs); + SetAssets(ref _buffDefs, (ReadOnlyContentPack contentPack) => contentPack.buffDefs); + SetAssets(ref _eliteDefs, (ReadOnlyContentPack contentPack) => contentPack.eliteDefs); + SetAssets(ref _unlockableDefs, (ReadOnlyContentPack contentPack) => contentPack.unlockableDefs); + yield return 0; + SetAssets(ref _survivorDefs, (ReadOnlyContentPack contentPack) => contentPack.survivorDefs); + SetAssets(ref _bodyPrefabs, (ReadOnlyContentPack contentPack) => contentPack.bodyPrefabs); + SetAssets(ref _masterPrefabs, (ReadOnlyContentPack contentPack) => contentPack.masterPrefabs); + SetAssets(ref _artifactDefs, (ReadOnlyContentPack contentPack) => contentPack.artifactDefs); + yield return 0; + SetAssets(ref _effectDefs, (ReadOnlyContentPack contentPack) => contentPack.effectDefs); + SetAssets(ref _skillDefs, (ReadOnlyContentPack contentPack) => contentPack.skillDefs); + SetAssets(ref _skillFamilies, (ReadOnlyContentPack contentPack) => contentPack.skillFamilies); + SetAssets(ref _surfaceDefs, (ReadOnlyContentPack contentPack) => contentPack.surfaceDefs); + SetAssets(ref _sceneDefs, (ReadOnlyContentPack contentPack) => contentPack.sceneDefs); + SetAssets(ref _projectilePrefabs, (ReadOnlyContentPack contentPack) => contentPack.projectilePrefabs); + yield return 0; + SetAssets(ref _networkSoundEventDefs, (ReadOnlyContentPack contentPack) => contentPack.networkSoundEventDefs); + SetAssets(ref _musicTrackDefs, (ReadOnlyContentPack contentPack) => contentPack.musicTrackDefs); + SetAssets(ref _networkedObjectPrefabs, (ReadOnlyContentPack contentPack) => contentPack.networkedObjectPrefabs); + SetAssets(ref _gameModePrefabs, (ReadOnlyContentPack contentPack) => contentPack.gameModePrefabs); + SetAssets(ref _gameEndingDefs, (ReadOnlyContentPack contentPack) => contentPack.gameEndingDefs); + SetAssets(ref _entityStateTypes, (ReadOnlyContentPack contentPack) => contentPack.entityStateTypes); + yield return 0; + SetAssets(ref _entityStateConfigurations, (ReadOnlyContentPack contentPack) => contentPack.entityStateConfigurations); + SetAssets(ref _expansionDefs, (ReadOnlyContentPack contentPack) => contentPack.expansionDefs); + SetAssets(ref _entitlementDefs, (ReadOnlyContentPack contentPack) => contentPack.entitlementDefs); + SetAssets(ref _miscPickupDefs, (ReadOnlyContentPack contentPack) => contentPack.miscPickupDefs); + yield return 0; + ContentManager.onContentPacksAssigned?.Invoke(allLoadedContentPacks); + void SetAssets(ref T[] field, Func> selector) + { + field = newContentPacks.SelectMany(selector).ToArray(); + } + } + + public static ReadOnlyContentPack? FindContentPack(string contentPackIdentifier) + { + int num = 0; + while (true) + { + int num2 = num; + ReadOnlyArray readOnlyArray = allLoadedContentPacks; + if (num2 >= readOnlyArray.Length) + { + break; + } + readOnlyArray = allLoadedContentPacks; + ref readonly ReadOnlyContentPack reference = ref readOnlyArray[num]; + if (string.Equals(reference.identifier, contentPackIdentifier, StringComparison.Ordinal)) + { + return reference; + } + num++; + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentPack.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentPack.cs new file mode 100644 index 0000000..6b659b9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentPack.cs @@ -0,0 +1,239 @@ +using System; +using JetBrains.Annotations; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Skills; +using UnityEngine; + +namespace RoR2.ContentManagement; + +public sealed class ContentPack +{ + [NotNull] + private string _identifier = "UNIDENTIFIED"; + + private static Func getGameObjectName = (GameObject obj) => obj.name; + + private static Func getComponentName = (Component obj) => obj.gameObject.name; + + private static Func getScriptableObjectName = (ScriptableObject obj) => obj.name; + + private static Func getEffectDefName = (EffectDef obj) => obj.prefabName; + + private static Func getTypeName = (Type obj) => obj.FullName; + + [NotNull] + public NamedAssetCollection bodyPrefabs = new NamedAssetCollection(getGameObjectName); + + [NotNull] + public NamedAssetCollection masterPrefabs = new NamedAssetCollection(getGameObjectName); + + [NotNull] + public NamedAssetCollection projectilePrefabs = new NamedAssetCollection(getGameObjectName); + + [NotNull] + public NamedAssetCollection gameModePrefabs = new NamedAssetCollection(getGameObjectName); + + [NotNull] + public NamedAssetCollection networkedObjectPrefabs = new NamedAssetCollection(getGameObjectName); + + [NotNull] + public NamedAssetCollection skillDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection skillFamilies = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection sceneDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection itemDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection itemTierDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection itemRelationshipProviders = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection itemRelationshipTypes = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection equipmentDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection buffDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection eliteDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection unlockableDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection survivorDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection artifactDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection effectDefs = new NamedAssetCollection(getEffectDefName); + + [NotNull] + public NamedAssetCollection surfaceDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection networkSoundEventDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection musicTrackDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection gameEndingDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection entityStateConfigurations = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection expansionDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection entitlementDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection miscPickupDefs = new NamedAssetCollection(getScriptableObjectName); + + [NotNull] + public NamedAssetCollection entityStateTypes = new NamedAssetCollection(getTypeName); + + private object[] assetCollections; + + [NotNull] + public string identifier + { + get + { + return _identifier; + } + internal set + { + _identifier = value ?? throw new ArgumentNullException("'identifier' cannot be null."); + } + } + + public ContentPack() + { + assetCollections = new object[28] + { + bodyPrefabs, masterPrefabs, projectilePrefabs, gameModePrefabs, networkedObjectPrefabs, skillDefs, skillFamilies, sceneDefs, itemDefs, itemTierDefs, + itemRelationshipProviders, itemRelationshipTypes, equipmentDefs, buffDefs, eliteDefs, unlockableDefs, survivorDefs, artifactDefs, effectDefs, surfaceDefs, + networkSoundEventDefs, musicTrackDefs, gameEndingDefs, entityStateConfigurations, expansionDefs, entitlementDefs, miscPickupDefs, entityStateTypes + }; + } + + public bool ValueEquals(ContentPack other) + { + return ValueEquals(this, other); + } + + public static void Copy([NotNull] ContentPack src, [NotNull] ContentPack dest) + { + src = src ?? throw new ArgumentNullException("src"); + dest = dest ?? throw new ArgumentNullException("dest"); + dest.identifier = src.identifier; + src.bodyPrefabs.CopyTo(dest.bodyPrefabs); + src.masterPrefabs.CopyTo(dest.masterPrefabs); + src.projectilePrefabs.CopyTo(dest.projectilePrefabs); + src.gameModePrefabs.CopyTo(dest.gameModePrefabs); + src.networkedObjectPrefabs.CopyTo(dest.networkedObjectPrefabs); + src.skillDefs.CopyTo(dest.skillDefs); + src.skillFamilies.CopyTo(dest.skillFamilies); + src.sceneDefs.CopyTo(dest.sceneDefs); + src.itemDefs.CopyTo(dest.itemDefs); + src.itemTierDefs.CopyTo(dest.itemTierDefs); + src.itemRelationshipProviders.CopyTo(dest.itemRelationshipProviders); + src.equipmentDefs.CopyTo(dest.equipmentDefs); + src.buffDefs.CopyTo(dest.buffDefs); + src.eliteDefs.CopyTo(dest.eliteDefs); + src.unlockableDefs.CopyTo(dest.unlockableDefs); + src.survivorDefs.CopyTo(dest.survivorDefs); + src.artifactDefs.CopyTo(dest.artifactDefs); + src.effectDefs.CopyTo(dest.effectDefs); + src.surfaceDefs.CopyTo(dest.surfaceDefs); + src.networkSoundEventDefs.CopyTo(dest.networkSoundEventDefs); + src.musicTrackDefs.CopyTo(dest.musicTrackDefs); + src.gameEndingDefs.CopyTo(dest.gameEndingDefs); + src.entityStateConfigurations.CopyTo(dest.entityStateConfigurations); + src.expansionDefs.CopyTo(dest.expansionDefs); + src.entitlementDefs.CopyTo(dest.entitlementDefs); + src.miscPickupDefs.CopyTo(dest.miscPickupDefs); + src.entityStateTypes.CopyTo(dest.entityStateTypes); + } + + public static bool ValueEquals([CanBeNull] ContentPack a, [CanBeNull] ContentPack b) + { + if (a == null != (b == null)) + { + return false; + } + if (a == null) + { + return true; + } + if (!a.identifier.Equals(b.identifier, StringComparison.Ordinal)) + { + return false; + } + if (a.bodyPrefabs.Equals(b.bodyPrefabs) && a.masterPrefabs.Equals(b.masterPrefabs) && a.projectilePrefabs.Equals(b.projectilePrefabs) && a.gameModePrefabs.Equals(b.gameModePrefabs) && a.networkedObjectPrefabs.Equals(b.networkedObjectPrefabs) && a.skillDefs.Equals(b.skillDefs) && a.skillFamilies.Equals(b.skillFamilies) && a.sceneDefs.Equals(b.sceneDefs) && a.itemDefs.Equals(b.itemDefs) && a.itemTierDefs.Equals(b.itemTierDefs) && a.itemRelationshipProviders.Equals(b.itemRelationshipProviders) && a.equipmentDefs.Equals(b.equipmentDefs) && a.buffDefs.Equals(b.buffDefs) && a.eliteDefs.Equals(b.eliteDefs) && a.unlockableDefs.Equals(b.unlockableDefs) && a.survivorDefs.Equals(b.survivorDefs) && a.artifactDefs.Equals(b.artifactDefs) && a.effectDefs.Equals(b.effectDefs) && a.surfaceDefs.Equals(b.surfaceDefs) && a.networkSoundEventDefs.Equals(b.networkSoundEventDefs) && a.musicTrackDefs.Equals(b.musicTrackDefs) && a.gameEndingDefs.Equals(b.gameEndingDefs) && a.entityStateConfigurations.Equals(b.entityStateConfigurations) && a.entityStateTypes.Equals(b.entityStateTypes) && a.expansionDefs.Equals(b.expansionDefs) && a.entitlementDefs.Equals(b.entitlementDefs)) + { + return a.miscPickupDefs.Equals(b.miscPickupDefs); + } + return false; + } + + private NamedAssetCollection FindAssetCollection(string collectionName) + { + return collectionName switch + { + "bodyPrefabs" => bodyPrefabs, + "masterPrefabs" => masterPrefabs, + "projectilePrefabs" => projectilePrefabs, + "gameModePrefabs" => gameModePrefabs, + "networkedObjectPrefabs" => networkedObjectPrefabs, + "skillDefs" => skillDefs, + "skillFamilies" => skillFamilies, + "sceneDefs" => sceneDefs, + "itemDefs" => itemDefs, + "itemTierDefs" => itemTierDefs, + "itemRelationshipProviders" => itemRelationshipProviders, + "itemRelationshipTypes" => itemRelationshipTypes, + "equipmentDefs" => equipmentDefs, + "buffDefs" => buffDefs, + "eliteDefs" => eliteDefs, + "unlockableDefs" => unlockableDefs, + "survivorDefs" => survivorDefs, + "artifactDefs" => artifactDefs, + "effectDefs" => effectDefs, + "surfaceDefs" => surfaceDefs, + "networkSoundEventDefs" => networkSoundEventDefs, + "musicTrackDefs" => musicTrackDefs, + "gameEndingDefs" => gameEndingDefs, + "entityStateConfigurations" => entityStateConfigurations, + "expansionDefs" => expansionDefs, + "entitlementDefs" => entitlementDefs, + "miscPickupDefs" => miscPickupDefs, + _ => null, + }; + } + + public bool FindAsset(string collectionName, string assetName, out object result) + { + NamedAssetCollection namedAssetCollection = FindAssetCollection(collectionName); + if (namedAssetCollection != null) + { + return namedAssetCollection.Find(assetName, out result); + } + result = null; + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentPackLoadInfo.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentPackLoadInfo.cs new file mode 100644 index 0000000..8aca20b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ContentPackLoadInfo.cs @@ -0,0 +1,14 @@ +namespace RoR2.ContentManagement; + +public struct ContentPackLoadInfo +{ + public int index; + + public string contentPackProviderIdentifier; + + public IContentPackProvider contentPackProvider; + + public ReadOnlyContentPack previousContentPack; + + public int retries; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/FinalizeAsyncArgs.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/FinalizeAsyncArgs.cs new file mode 100644 index 0000000..8b2addd --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/FinalizeAsyncArgs.cs @@ -0,0 +1,23 @@ +using System; +using HG; + +namespace RoR2.ContentManagement; + +public class FinalizeAsyncArgs +{ + private readonly IProgress progressReceiver; + + public readonly ReadOnlyArray peerLoadInfos; + + public readonly ReadOnlyContentPack finalContentPack; + + public FinalizeAsyncArgs(IProgress progressReceiver, ReadOnlyArray peerLoadInfos, ReadOnlyContentPack finalContentPack) + { + this.progressReceiver = progressReceiver; + } + + public void ReportProgress(float progress) + { + progressReceiver.Report(progress); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/GetContentPackAsyncArgs.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/GetContentPackAsyncArgs.cs new file mode 100644 index 0000000..e950006 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/GetContentPackAsyncArgs.cs @@ -0,0 +1,28 @@ +using System; +using HG; + +namespace RoR2.ContentManagement; + +public class GetContentPackAsyncArgs +{ + private readonly IProgress progressReceiver; + + public readonly ReadOnlyArray peerLoadInfos; + + public readonly ContentPack output; + + public readonly int retriesRemaining; + + public GetContentPackAsyncArgs(IProgress progressReceiver, ContentPack output, ReadOnlyArray peerLoadInfos, int retriesRemaining) + { + this.progressReceiver = progressReceiver; + this.output = output; + this.peerLoadInfos = peerLoadInfos; + this.retriesRemaining = retriesRemaining; + } + + public void ReportProgress(float progress) + { + progressReceiver.Report(progress); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/IContentPackProvider.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/IContentPackProvider.cs new file mode 100644 index 0000000..bcdf459 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/IContentPackProvider.cs @@ -0,0 +1,14 @@ +using System.Collections; + +namespace RoR2.ContentManagement; + +public interface IContentPackProvider +{ + string identifier { get; } + + IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args); + + IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args); + + IEnumerator FinalizeAsync(FinalizeAsyncArgs args); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/LoadStaticContentAsyncArgs.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/LoadStaticContentAsyncArgs.cs new file mode 100644 index 0000000..5809939 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/LoadStaticContentAsyncArgs.cs @@ -0,0 +1,22 @@ +using System; +using HG; + +namespace RoR2.ContentManagement; + +public class LoadStaticContentAsyncArgs +{ + private readonly IProgress progressReceiver; + + public readonly ReadOnlyArray peerLoadInfos; + + public LoadStaticContentAsyncArgs(IProgress progressReceiver, ReadOnlyArray peerLoadInfos) + { + this.progressReceiver = progressReceiver; + this.peerLoadInfos = peerLoadInfos; + } + + public void ReportProgress(float progress) + { + progressReceiver.Report(progress); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/NamedAssetCollection.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/NamedAssetCollection.cs new file mode 100644 index 0000000..b694630 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/NamedAssetCollection.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using HG; +using JetBrains.Annotations; + +namespace RoR2.ContentManagement; + +public abstract class NamedAssetCollection +{ + [CanBeNull] + public abstract bool Find([NotNull] string assetName, out object result); +} +public class NamedAssetCollection : NamedAssetCollection, IEquatable>, IEnumerable, IEnumerable +{ + private struct AssetInfo : IComparable, IEquatable + { + public TAsset asset; + + public string assetName; + + public int CompareTo(AssetInfo other) + { + return string.Compare(assetName, other.assetName, StringComparison.OrdinalIgnoreCase); + } + + public bool Equals(AssetInfo other) + { + if (object.Equals(asset, other.asset)) + { + return string.Equals(assetName, other.assetName, StringComparison.Ordinal); + } + return false; + } + } + + public struct AssetEnumerator : IEnumerator, IEnumerator, IDisposable + { + private int i; + + private NamedAssetCollection src; + + public TAsset Current => src.assetInfos[i].asset; + + object IEnumerator.Current => Current; + + public AssetEnumerator(NamedAssetCollection src) + { + this.src = src; + i = -1; + } + + public void Dispose() + { + } + + public bool MoveNext() + { + i++; + return i < src.Length; + } + + public void Reset() + { + i = -1; + } + } + + private Dictionary assetToName = new Dictionary(); + + private Dictionary nameToAsset = new Dictionary(); + + private AssetInfo[] assetInfos = Array.Empty(); + + private Func nameProvider; + + public int Length => assetInfos.Length; + + public int Count => Length; + + public bool IsReadOnly => false; + + public TAsset this[int i] => assetInfos[i].asset; + + public NamedAssetCollection([NotNull] Func nameProvider) + { + this.nameProvider = nameProvider; + } + + public void Add([NotNull] TAsset[] newAssets) + { + string[] array = new string[newAssets.Length]; + for (int i = 0; i < newAssets.Length; i++) + { + array[i] = nameProvider(newAssets[i]); + } + for (int j = 0; j < newAssets.Length; j++) + { + TAsset val = newAssets[j]; + string text = array[j]; + if (assetToName.ContainsKey(val)) + { + throw new ArgumentException($"Asset {val} is already registered!"); + } + if (nameToAsset.ContainsKey(text)) + { + throw new ArgumentException("Asset name " + text + " is already registered!"); + } + } + int num = assetInfos.Length; + int newSize = num + newAssets.Length; + Array.Resize(ref assetInfos, newSize); + for (int k = 0; k < newAssets.Length; k++) + { + TAsset val2 = newAssets[k]; + string text2 = array[k]; + assetInfos[num + k] = new AssetInfo + { + asset = val2, + assetName = text2 + }; + nameToAsset[text2] = val2; + assetToName[val2] = text2; + } + Array.Sort(assetInfos); + } + + [CanBeNull] + public TAsset Find([NotNull] string assetName) + { + if (!nameToAsset.TryGetValue(assetName, out var value)) + { + return default(TAsset); + } + return value; + } + + [CanBeNull] + public override bool Find([NotNull] string assetName, out object result) + { + TAsset value; + bool result2 = nameToAsset.TryGetValue(assetName, out value); + result = value; + return result2; + } + + [CanBeNull] + public string GetAssetName([NotNull] TAsset asset) + { + if (!assetToName.TryGetValue(asset, out var value)) + { + return null; + } + return value; + } + + public bool Contains([NotNull] TAsset asset) + { + return assetToName.ContainsKey(asset); + } + + public void Clear() + { + assetToName.Clear(); + nameToAsset.Clear(); + assetInfos = Array.Empty(); + } + + public override bool Equals(object obj) + { + if (!(obj is NamedAssetCollection other)) + { + return false; + } + return Equals(other); + } + + public bool Equals(NamedAssetCollection other) + { + if (this == other) + { + return true; + } + if (assetInfos.Length != other.assetInfos.Length) + { + return false; + } + int i = 0; + for (int num = assetInfos.Length; i < num; i++) + { + if (!assetInfos[i].Equals(other.assetInfos[i])) + { + return false; + } + } + return true; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public static void Copy(NamedAssetCollection src, NamedAssetCollection dest) + { + dest.assetInfos = ArrayUtils.Clone(src.assetInfos); + dest.assetToName = new Dictionary(src.assetToName); + dest.nameToAsset = new Dictionary(src.nameToAsset); + dest.nameProvider = src.nameProvider; + } + + public void CopyTo(NamedAssetCollection dest) + { + Copy(this, dest); + } + + public AssetEnumerator GetEnumerator() + { + return new AssetEnumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ReadOnlyContentPack.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ReadOnlyContentPack.cs new file mode 100644 index 0000000..303adfc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ReadOnlyContentPack.cs @@ -0,0 +1,93 @@ +using System; +using JetBrains.Annotations; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Skills; +using UnityEngine; + +namespace RoR2.ContentManagement; + +public readonly struct ReadOnlyContentPack +{ + private readonly ContentPack src; + + public bool isValid => src != null; + + public string identifier => src.identifier; + + public ReadOnlyNamedAssetCollection bodyPrefabs => src.bodyPrefabs; + + public ReadOnlyNamedAssetCollection masterPrefabs => src.masterPrefabs; + + public ReadOnlyNamedAssetCollection projectilePrefabs => src.projectilePrefabs; + + public ReadOnlyNamedAssetCollection gameModePrefabs => src.gameModePrefabs; + + public ReadOnlyNamedAssetCollection networkedObjectPrefabs => src.networkedObjectPrefabs; + + public ReadOnlyNamedAssetCollection skillDefs => src.skillDefs; + + public ReadOnlyNamedAssetCollection skillFamilies => src.skillFamilies; + + public ReadOnlyNamedAssetCollection sceneDefs => src.sceneDefs; + + public ReadOnlyNamedAssetCollection itemDefs => src.itemDefs; + + public ReadOnlyNamedAssetCollection itemTierDefs => src.itemTierDefs; + + public ReadOnlyNamedAssetCollection itemRelationshipProviders => src.itemRelationshipProviders; + + public ReadOnlyNamedAssetCollection itemRelationshipTypes => src.itemRelationshipTypes; + + public ReadOnlyNamedAssetCollection equipmentDefs => src.equipmentDefs; + + public ReadOnlyNamedAssetCollection buffDefs => src.buffDefs; + + public ReadOnlyNamedAssetCollection eliteDefs => src.eliteDefs; + + public ReadOnlyNamedAssetCollection unlockableDefs => src.unlockableDefs; + + public ReadOnlyNamedAssetCollection survivorDefs => src.survivorDefs; + + public ReadOnlyNamedAssetCollection artifactDefs => src.artifactDefs; + + public ReadOnlyNamedAssetCollection effectDefs => src.effectDefs; + + public ReadOnlyNamedAssetCollection surfaceDefs => src.surfaceDefs; + + public ReadOnlyNamedAssetCollection networkSoundEventDefs => src.networkSoundEventDefs; + + public ReadOnlyNamedAssetCollection musicTrackDefs => src.musicTrackDefs; + + public ReadOnlyNamedAssetCollection gameEndingDefs => src.gameEndingDefs; + + public ReadOnlyNamedAssetCollection entityStateConfigurations => src.entityStateConfigurations; + + public ReadOnlyNamedAssetCollection expansionDefs => src.expansionDefs; + + public ReadOnlyNamedAssetCollection entitlementDefs => src.entitlementDefs; + + public ReadOnlyNamedAssetCollection miscPickupDefs => src.miscPickupDefs; + + public ReadOnlyNamedAssetCollection entityStateTypes => src.entityStateTypes; + + public ReadOnlyContentPack([NotNull] ContentPack src) + { + this.src = src ?? throw new ArgumentNullException("src"); + } + + public bool ValueEquals(in ReadOnlyContentPack other) + { + return src.ValueEquals(other.src); + } + + public static implicit operator ReadOnlyContentPack([NotNull] ContentPack contentPack) + { + return new ReadOnlyContentPack(contentPack); + } + + public bool FindAsset(string collectionName, string assetName, out object result) + { + return src.FindAsset(collectionName, assetName, out result); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ReadOnlyNamedAssetCollection.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ReadOnlyNamedAssetCollection.cs new file mode 100644 index 0000000..de0428f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/ReadOnlyNamedAssetCollection.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace RoR2.ContentManagement; + +public readonly struct ReadOnlyNamedAssetCollection : IEnumerable, IEnumerable, IEquatable> +{ + private readonly NamedAssetCollection src; + + public int Length => src.Length; + + public ReadOnlyNamedAssetCollection(NamedAssetCollection src) + { + this.src = src; + } + + public TAsset Find(string assetName) + { + return src.Find(assetName); + } + + public bool Find(string assetName, out object result) + { + return src.Find(assetName, out result); + } + + public string GetAssetName(TAsset asset) + { + return src.GetAssetName(asset); + } + + public bool Contains([NotNull] TAsset asset) + { + return src.Contains(asset); + } + + public static void Copy(ReadOnlyNamedAssetCollection src, NamedAssetCollection dest) + { + NamedAssetCollection.Copy(src.src, dest); + } + + public void CopyTo(NamedAssetCollection dest) + { + src.CopyTo(dest); + } + + public override bool Equals(object obj) + { + if (obj is NamedAssetCollection namedAssetCollection) + { + return Equals(namedAssetCollection); + } + return false; + } + + public override int GetHashCode() + { + return src.GetHashCode(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public NamedAssetCollection.AssetEnumerator GetEnumerator() + { + return src.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public bool Equals(ReadOnlyNamedAssetCollection other) + { + return src.Equals(other.src); + } + + public static implicit operator ReadOnlyNamedAssetCollection(NamedAssetCollection src) + { + return new ReadOnlyNamedAssetCollection(src); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/SerializableContentPack.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/SerializableContentPack.cs new file mode 100644 index 0000000..9a1c811 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/SerializableContentPack.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using EntityStates; +using RoR2.Skills; +using UnityEngine; + +namespace RoR2.ContentManagement; + +[CreateAssetMenu(menuName = "RoR2/SerializableContentPack")] +public class SerializableContentPack : ScriptableObject +{ + public GameObject[] bodyPrefabs = Array.Empty(); + + public GameObject[] masterPrefabs = Array.Empty(); + + public GameObject[] projectilePrefabs = Array.Empty(); + + public GameObject[] gameModePrefabs = Array.Empty(); + + public GameObject[] networkedObjectPrefabs = Array.Empty(); + + public SkillDef[] skillDefs = Array.Empty(); + + public SkillFamily[] skillFamilies = Array.Empty(); + + public SceneDef[] sceneDefs = Array.Empty(); + + public ItemDef[] itemDefs = Array.Empty(); + + public EquipmentDef[] equipmentDefs = Array.Empty(); + + public BuffDef[] buffDefs = Array.Empty(); + + public EliteDef[] eliteDefs = Array.Empty(); + + public UnlockableDef[] unlockableDefs = Array.Empty(); + + public SurvivorDef[] survivorDefs = Array.Empty(); + + public ArtifactDef[] artifactDefs = Array.Empty(); + + public GameObject[] effectDefs = Array.Empty(); + + public SurfaceDef[] surfaceDefs = Array.Empty(); + + public NetworkSoundEventDef[] networkSoundEventDefs = Array.Empty(); + + public MusicTrackDef[] musicTrackDefs = Array.Empty(); + + public GameEndingDef[] gameEndingDefs = Array.Empty(); + + public EntityStateConfiguration[] entityStateConfigurations = Array.Empty(); + + public SerializableEntityStateType[] entityStateTypes = Array.Empty(); + + public ContentPack CreateV1_1_1_4_ContentPack() + { + ContentPack contentPack = new ContentPack(); + contentPack.bodyPrefabs.Add(bodyPrefabs); + contentPack.masterPrefabs.Add(masterPrefabs); + contentPack.projectilePrefabs.Add(projectilePrefabs); + contentPack.gameModePrefabs.Add(gameModePrefabs); + contentPack.networkedObjectPrefabs.Add(networkedObjectPrefabs); + contentPack.skillDefs.Add(skillDefs); + contentPack.skillFamilies.Add(skillFamilies); + contentPack.sceneDefs.Add(sceneDefs); + contentPack.itemDefs.Add(itemDefs); + contentPack.equipmentDefs.Add(equipmentDefs); + contentPack.buffDefs.Add(buffDefs); + contentPack.eliteDefs.Add(eliteDefs); + contentPack.unlockableDefs.Add(unlockableDefs); + contentPack.survivorDefs.Add(survivorDefs); + contentPack.artifactDefs.Add(artifactDefs); + contentPack.effectDefs.Add(effectDefs.Select((GameObject asset) => new EffectDef(asset)).ToArray()); + contentPack.surfaceDefs.Add(surfaceDefs); + contentPack.networkSoundEventDefs.Add(networkSoundEventDefs); + contentPack.musicTrackDefs.Add(musicTrackDefs); + contentPack.gameEndingDefs.Add(gameEndingDefs); + contentPack.entityStateConfigurations.Add(entityStateConfigurations); + List list = new List(); + for (int i = 0; i < entityStateTypes.Length; i++) + { + Type stateType = entityStateTypes[i].stateType; + if (stateType != null) + { + list.Add(stateType); + continue; + } + Debug.LogWarning("SerializableContentPack \"" + base.name + "\" could not resolve type with name \"" + entityStateTypes[i].typeName + "\". The type will not be available in the content pack."); + } + contentPack.entityStateTypes.Add(list.ToArray()); + return contentPack; + } + + public virtual ContentPack CreateContentPack() + { + return CreateV1_1_1_4_ContentPack(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/SimpleContentPackProvider.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/SimpleContentPackProvider.cs new file mode 100644 index 0000000..b8f9bd0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/SimpleContentPackProvider.cs @@ -0,0 +1,35 @@ +using System.Collections; + +namespace RoR2.ContentManagement; + +public class SimpleContentPackProvider : IContentPackProvider +{ + public delegate IEnumerator LoadStaticContentAsyncDelegate(LoadStaticContentAsyncArgs args); + + public delegate IEnumerator GenerateContentPackAsyncDelegate(GetContentPackAsyncArgs args); + + public delegate IEnumerator FinalizeAsyncDelegate(FinalizeAsyncArgs args); + + public string identifier { get; set; } + + public LoadStaticContentAsyncDelegate loadStaticContentImplementation { get; set; } + + public GenerateContentPackAsyncDelegate generateContentPackAsyncImplementation { get; set; } + + public FinalizeAsyncDelegate finalizeAsyncImplementation { get; set; } + + public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) + { + return loadStaticContentImplementation?.Invoke(args); + } + + public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) + { + return generateContentPackAsyncImplementation?.Invoke(args); + } + + public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) + { + return finalizeAsyncImplementation?.Invoke(args); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ContentManagement/TargetAssetNameAttribute.cs b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/TargetAssetNameAttribute.cs new file mode 100644 index 0000000..14df060 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ContentManagement/TargetAssetNameAttribute.cs @@ -0,0 +1,13 @@ +using System; + +namespace RoR2.ContentManagement; + +public class TargetAssetNameAttribute : Attribute +{ + public readonly string targetAssetName; + + public TargetAssetNameAttribute(string targetAssetName) + { + this.targetAssetName = targetAssetName; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/BaseDirectionalSearch.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/BaseDirectionalSearch.cs new file mode 100644 index 0000000..9962eb1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/BaseDirectionalSearch.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using HG; +using UnityEngine; + +namespace RoR2.DirectionalSearch; + +public class BaseDirectionalSearch where TSource : class where TSelector : IGenericWorldSearchSelector where TCandidateFilter : IGenericDirectionalSearchFilter +{ + private struct CandidateInfo + { + public TSource source; + + public Vector3 position; + + public Vector3 diff; + + public float distance; + + public float dot; + + public GameObject entity; + } + + public Vector3 searchOrigin; + + public Vector3 searchDirection; + + private float minThetaDot = -1f; + + private float maxThetaDot = 1f; + + public float minDistanceFilter; + + public float maxDistanceFilter = float.PositiveInfinity; + + public SortMode sortMode = SortMode.Distance; + + public bool filterByLoS = true; + + public bool filterByDistinctEntity; + + private CandidateInfo[] candidateInfoList = Array.Empty(); + + private int candidateCount; + + protected TSelector selector; + + protected TCandidateFilter candidateFilter; + + public float minAngleFilter + { + set + { + maxThetaDot = Mathf.Cos(Mathf.Clamp(value, 0f, 180f) * (MathF.PI / 180f)); + } + } + + public float maxAngleFilter + { + set + { + minThetaDot = Mathf.Cos(Mathf.Clamp(value, 0f, 180f) * (MathF.PI / 180f)); + } + } + + public BaseDirectionalSearch(TSelector selector, TCandidateFilter candidateFilter) + { + this.selector = selector; + this.candidateFilter = candidateFilter; + } + + public TSource SearchCandidatesForSingleTarget(TSourceEnumerable sourceEnumerable) where TSourceEnumerable : IEnumerable + { + ArrayUtils.Clear(candidateInfoList, ref candidateCount); + float num = minDistanceFilter * minDistanceFilter; + float num2 = maxDistanceFilter * maxDistanceFilter; + foreach (TSource item in sourceEnumerable) + { + CandidateInfo candidateInfo = default(CandidateInfo); + candidateInfo.source = item; + CandidateInfo value = candidateInfo; + Transform transform = selector.GetTransform(item); + if (!transform) + { + continue; + } + value.position = transform.position; + value.diff = value.position - searchOrigin; + float sqrMagnitude = value.diff.sqrMagnitude; + if (!(sqrMagnitude < num) && !(sqrMagnitude > num2)) + { + value.distance = Mathf.Sqrt(sqrMagnitude); + value.dot = ((value.distance == 0f) ? 0f : Vector3.Dot(searchDirection, value.diff / value.distance)); + if (!(value.dot < minThetaDot) && !(value.dot > maxThetaDot)) + { + value.entity = selector.GetRootObject(item); + ArrayUtils.ArrayAppend(ref candidateInfoList, ref candidateCount, in value); + } + } + } + for (int num3 = candidateCount - 1; num3 >= 0; num3--) + { + if (!candidateFilter.PassesFilter(candidateInfoList[num3].source)) + { + ArrayUtils.ArrayRemoveAt(candidateInfoList, ref candidateCount, num3); + } + } + Array.Sort(candidateInfoList, GetSorter()); + if (filterByDistinctEntity) + { + for (int num4 = candidateCount - 1; num4 >= 0; num4--) + { + ref CandidateInfo reference = ref candidateInfoList[num4]; + for (int i = 0; i < num4; i++) + { + ref CandidateInfo reference2 = ref candidateInfoList[i]; + if (reference.entity == reference2.entity) + { + ArrayUtils.ArrayRemoveAt(candidateInfoList, ref candidateCount, num4); + break; + } + } + } + } + TSource result = null; + if (filterByLoS) + { + for (int j = 0; j < candidateCount; j++) + { + if (!Physics.Linecast(searchOrigin, candidateInfoList[j].position, out var _, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + result = candidateInfoList[j].source; + break; + } + } + } + else if (candidateCount > 0) + { + result = candidateInfoList[0].source; + } + ArrayUtils.Clear(candidateInfoList, ref candidateCount); + return result; + } + + private static int DistanceToInversePriority(CandidateInfo a, CandidateInfo b) + { + return a.distance.CompareTo(b.distance); + } + + private static int AngleToInversePriority(CandidateInfo a, CandidateInfo b) + { + return (0f - a.dot).CompareTo(0f - b.dot); + } + + private static int DistanceAndAngleToInversePriority(CandidateInfo a, CandidateInfo b) + { + return ((0f - a.dot) * a.distance).CompareTo((0f - b.dot) * b.distance); + } + + private Comparison GetSorter() + { + return sortMode switch + { + SortMode.Distance => DistanceToInversePriority, + SortMode.Angle => AngleToInversePriority, + SortMode.DistanceAndAngle => DistanceAndAngleToInversePriority, + _ => null, + }; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/IGenericDirectionalSearchFilter.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/IGenericDirectionalSearchFilter.cs new file mode 100644 index 0000000..8c13a4b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/IGenericDirectionalSearchFilter.cs @@ -0,0 +1,6 @@ +namespace RoR2.DirectionalSearch; + +public interface IGenericDirectionalSearchFilter +{ + bool PassesFilter(TSource candidateInfo); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/IGenericWorldSearchSelector.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/IGenericWorldSearchSelector.cs new file mode 100644 index 0000000..39f3607 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/IGenericWorldSearchSelector.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RoR2.DirectionalSearch; + +public interface IGenericWorldSearchSelector +{ + Transform GetTransform(TSource source); + + GameObject GetRootObject(TSource source); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearch.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearch.cs new file mode 100644 index 0000000..7cf95ae --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearch.cs @@ -0,0 +1,26 @@ +namespace RoR2.DirectionalSearch; + +public class PickupSearch : BaseDirectionalSearch +{ + public bool requireTransmutable + { + get + { + return candidateFilter.requireTransmutable; + } + set + { + candidateFilter.requireTransmutable = value; + } + } + + public PickupSearch() + : base(default(PickupSearchSelector), default(PickupSearchFilter)) + { + } + + public PickupSearch(PickupSearchSelector selector, PickupSearchFilter candidateFilter) + : base(selector, candidateFilter) + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearchFilter.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearchFilter.cs new file mode 100644 index 0000000..993200b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearchFilter.cs @@ -0,0 +1,15 @@ +namespace RoR2.DirectionalSearch; + +public struct PickupSearchFilter : IGenericDirectionalSearchFilter +{ + public bool requireTransmutable; + + public bool PassesFilter(GenericPickupController genericPickupController) + { + if (requireTransmutable) + { + return PickupTransmutationManager.GetAvailableGroupFromPickupIndex(genericPickupController.pickupIndex) != null; + } + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearchSelector.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearchSelector.cs new file mode 100644 index 0000000..f48164c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/PickupSearchSelector.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; +using UnityEngine; + +namespace RoR2.DirectionalSearch; + +[StructLayout(LayoutKind.Sequential, Size = 1)] +public struct PickupSearchSelector : IGenericWorldSearchSelector +{ + public Transform GetTransform(GenericPickupController source) + { + return source.pickupDisplay.transform; + } + + public GameObject GetRootObject(GenericPickupController source) + { + return source.gameObject; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/SortMode.cs b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/SortMode.cs new file mode 100644 index 0000000..851deda --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DirectionalSearch/SortMode.cs @@ -0,0 +1,9 @@ +namespace RoR2.DirectionalSearch; + +public enum SortMode +{ + None, + Distance, + Angle, + DistanceAndAngle +} diff --git a/ilspy_dump/ror2_csproj/RoR2.DispatachableEffects/AddOverlayToReferencedObject.cs b/ilspy_dump/ror2_csproj/RoR2.DispatachableEffects/AddOverlayToReferencedObject.cs new file mode 100644 index 0000000..534061a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.DispatachableEffects/AddOverlayToReferencedObject.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace RoR2.DispatachableEffects; + +[RequireComponent(typeof(EffectComponent))] +[RequireComponent(typeof(TemporaryOverlay))] +public class AddOverlayToReferencedObject : MonoBehaviour +{ + public bool effectDataGenericFloatOverridesDuration = true; + + protected void Start() + { + EffectComponent component = GetComponent(); + ApplyOverlay(component.GetReferencedObject(), component.effectData.genericFloat); + } + + protected void ApplyOverlay(GameObject targetObject, float duration) + { + if (!targetObject) + { + return; + } + ModelLocator component = targetObject.GetComponent(); + if (!component) + { + return; + } + Transform modelTransform = component.modelTransform; + if (!modelTransform) + { + return; + } + CharacterModel component2 = modelTransform.GetComponent(); + if ((bool)component2) + { + TemporaryOverlay component3 = GetComponent(); + if ((bool)component3) + { + component3.AddToCharacerModel(component2); + } + if (effectDataGenericFloatOverridesDuration) + { + component3.durationInstance = duration; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/BaseUserEntitlementTracker.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/BaseUserEntitlementTracker.cs new file mode 100644 index 0000000..5b7ac19 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/BaseUserEntitlementTracker.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using HG; +using JetBrains.Annotations; +using RoR2.ExpansionManagement; +using UnityEngine; + +namespace RoR2.EntitlementManagement; + +public abstract class BaseUserEntitlementTracker : IDisposable where TUser : class +{ + private Dictionary> userToEntitlements = new Dictionary>(); + + private IUserEntitlementResolver[] entitlementResolvers; + + private bool disposed; + + public static Action OnUserEntitlementsUpdated; + + public static Action OnAllUserEntitlementsUpdated; + + protected abstract void SubscribeToUserDiscovered(); + + protected abstract void SubscribeToUserLost(); + + protected abstract void UnsubscribeFromUserDiscovered(); + + protected abstract void UnsubscribeFromUserLost(); + + protected abstract IList GetCurrentUsers(); + + public BaseUserEntitlementTracker(IUserEntitlementResolver[] entitlementResolvers) + { + this.entitlementResolvers = ArrayUtils.Clone(entitlementResolvers); + SubscribeToUserDiscovered(); + SubscribeToUserLost(); + for (int i = 0; i < entitlementResolvers.Length; i++) + { + entitlementResolvers[i].onEntitlementsChanged += UpdateAllUserEntitlements; + } + IList currentUsers = GetCurrentUsers(); + for (int j = 0; j < currentUsers.Count; j++) + { + OnUserDiscovered(currentUsers[j]); + } + } + + public virtual void Dispose() + { + disposed = true; + for (int num = entitlementResolvers.Length - 1; num >= 0; num--) + { + entitlementResolvers[num].onEntitlementsChanged -= UpdateAllUserEntitlements; + } + UnsubscribeFromUserLost(); + UnsubscribeFromUserDiscovered(); + IList currentUsers = GetCurrentUsers(); + for (int i = 0; i < currentUsers.Count; i++) + { + OnUserLost(currentUsers[i]); + } + } + + protected virtual void OnUserDiscovered(TUser user) + { + try + { + List value = new List(); + userToEntitlements.Add(user, value); + UpdateUserEntitlements(user); + } + catch (Exception message) + { + LogError(message); + } + } + + protected virtual void OnUserLost(TUser user) + { + try + { + userToEntitlements.Remove(user); + } + catch (Exception message) + { + LogError(message); + } + } + + public void UpdateAllUserEntitlements() + { + IList currentUsers = GetCurrentUsers(); + for (int i = 0; i < currentUsers.Count; i++) + { + UpdateUserEntitlements(currentUsers[i]); + } + OnAllUserEntitlementsUpdated?.Invoke(); + } + + protected void UpdateUserEntitlements(TUser user) + { + if (!userToEntitlements.TryGetValue(user, out var value)) + { + return; + } + value.Clear(); + IUserEntitlementResolver[] array = entitlementResolvers; + foreach (IUserEntitlementResolver userEntitlementResolver in array) + { + foreach (EntitlementDef entitlementDef in EntitlementCatalog.entitlementDefs) + { + if (!value.Contains(entitlementDef) && userEntitlementResolver.CheckUserHasEntitlement(user, entitlementDef)) + { + value.Add(entitlementDef); + } + } + } + OnUserEntitlementsUpdated?.Invoke(); + } + + public bool UserHasEntitlement([NotNull] TUser user, [NotNull] EntitlementDef entitlementDef) + { + if (!entitlementDef) + { + throw new ArgumentNullException("entitlementDef"); + } + if (user == null || !userToEntitlements.TryGetValue(user, out var value)) + { + return false; + } + return value.Contains(entitlementDef); + } + + public bool AnyUserHasEntitlement([NotNull] EntitlementDef entitlementDef) + { + IList currentUsers = GetCurrentUsers(); + for (int i = 0; i < currentUsers.Count; i++) + { + if (UserHasEntitlement(currentUsers[i], entitlementDef)) + { + return true; + } + } + return false; + } + + public bool UserHasEntitlementForUnlockable([NotNull] TUser user, UnlockableDef unlockableDef) + { + if (!unlockableDef) + { + return true; + } + if (user == null || !userToEntitlements.TryGetValue(user, out var value)) + { + return false; + } + ExpansionDef expansionDefForUnlockable = UnlockableCatalog.GetExpansionDefForUnlockable(unlockableDef.index); + if (!expansionDefForUnlockable) + { + return true; + } + EntitlementDef requiredEntitlement = expansionDefForUnlockable.requiredEntitlement; + return value.Contains(requiredEntitlement); + } + + protected static void LogError(object message) + { + RoR2Application.onNextUpdate += delegate + { + Debug.LogError(message); + }; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/ConCommandArgExtensions.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/ConCommandArgExtensions.cs new file mode 100644 index 0000000..528f6fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/ConCommandArgExtensions.cs @@ -0,0 +1,25 @@ +using System; + +namespace RoR2.EntitlementManagement; + +public static class ConCommandArgExtensions +{ + public static EntitlementIndex? TryGetArgEntitlementIndex(this ConCommandArgs args, int index) + { + string text = args.TryGetArgString(index); + if (text != null) + { + EntitlementIndex entitlementIndex = EntitlementCatalog.FindEntitlementIndex(text); + if (entitlementIndex != EntitlementIndex.None || text.Equals("None", StringComparison.Ordinal)) + { + return entitlementIndex; + } + } + return null; + } + + public static EntitlementIndex GetArgEntitlementIndex(this ConCommandArgs args, int index) + { + return args.TryGetArgEntitlementIndex(index) ?? throw new ConCommandException("No EntitlementIndex is defined for an entitlement named '" + args.TryGetArgString(index) + "'. Use the \"entitlement_list\" command to get a list of all valid entitlements."); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EgsEntitlementResolver.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EgsEntitlementResolver.cs new file mode 100644 index 0000000..24cdec4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EgsEntitlementResolver.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Epic.OnlineServices; +using Epic.OnlineServices.Ecom; +using JetBrains.Annotations; +using RoR2.ContentManagement; +using RoR2.Networking; + +namespace RoR2.EntitlementManagement; + +public class EgsEntitlementResolver : IUserEntitementsResolverNetworkAndLocal, IUserEntitlementResolver, IUserEntitlementResolver, IPlatformShopLauncher +{ + private const string DevAudienceEntitlementName = "8fc64849a03741faaf51824d6e727cc1"; + + private static EcomInterface EOS_Ecom; + + private List ownedEntitlementIDs = new List(); + + private static event Action onDlcInstalled; + + public event Action OnPlatformShopClosed; + + event Action IUserEntitlementResolver.onEntitlementsChanged + { + add + { + onDlcInstalled += value; + } + remove + { + onDlcInstalled -= value; + } + } + + event Action IUserEntitlementResolver.onEntitlementsChanged + { + add + { + onDlcInstalled += value; + } + remove + { + onDlcInstalled -= value; + } + } + + public EgsEntitlementResolver() + { + if (EOS_Ecom == null) + { + EOS_Ecom = EOSPlatformManager.GetPlatformInterface().GetEcomInterface(); + } + RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(GetEGSEntitlements)); + } + + private void GetEGSEntitlements(EpicAccountId accountId) + { + GetEGSEntitlements(); + } + + private void GetEGSEntitlements() + { + if (EOSLoginManager.loggedInAuthId != null) + { + QueryOwnershipOptions options = default(QueryOwnershipOptions); + options.LocalUserId = EOSLoginManager.loggedInAuthId; + options.CatalogItemIds = EntitlementCatalog.entitlementDefs.Select((EntitlementDef x) => new Utf8String(x.eosItemId)).ToArray(); + EOS_Ecom.QueryOwnership(ref options, null, HandleQueryOwnershipCallback); + } + else + { + EOSLoginManager.OnAuthLoggedIn += GetEGSEntitlements; + } + } + + private void HandleQueryOwnershipCallback(ref QueryOwnershipCallbackInfo data) + { + if (data.GetResultCode() == Result.Success) + { + ownedEntitlementIDs.Clear(); + for (int i = 0; i < data.ItemOwnership.Length; i++) + { + if (data.ItemOwnership[i].OwnershipStatus == OwnershipStatus.Owned) + { + ownedEntitlementIDs.Add(data.ItemOwnership[i].Id); + } + } + } + EgsEntitlementResolver.onDlcInstalled(); + } + + bool IUserEntitlementResolver.CheckUserHasEntitlement([NotNull] LocalUser localUser, [NotNull] EntitlementDef entitlementDef) + { + return CheckLocalUserHasEntitlement(entitlementDef); + } + + private bool CheckLocalUserHasEntitlement(EntitlementDef entitlementDef) + { + for (int i = 0; i < ownedEntitlementIDs.Count; i++) + { + if (ownedEntitlementIDs[i] == entitlementDef.eosItemId) + { + return true; + } + } + return false; + } + + bool IUserEntitlementResolver.CheckUserHasEntitlement([NotNull] NetworkUser networkUser, [NotNull] EntitlementDef entitlementDef) + { + if (!networkUser) + { + return false; + } + if (networkUser.isLocalPlayer) + { + return CheckLocalUserHasEntitlement(entitlementDef); + } + ClientAuthData clientAuthData = ServerAuthManager.FindAuthData(networkUser.connectionToClient); + if (clientAuthData == null) + { + return false; + } + PlatformID platformId = clientAuthData.platformId; + if (!platformId.isValid) + { + return false; + } + return EntitlementAbstractions.VerifyRemoteUser(clientAuthData, entitlementDef); + } + + public string[] BuildEntitlements() + { + string[] array = new string[ownedEntitlementIDs.Count]; + int num = array.Length; + for (int i = 0; i < num; i++) + { + EntitlementDef[] entitlementDefs = ContentManager.entitlementDefs; + foreach (EntitlementDef entitlementDef in entitlementDefs) + { + if (entitlementDef.eosItemId == ownedEntitlementIDs[i] || "8fc64849a03741faaf51824d6e727cc1" == ownedEntitlementIDs[i]) + { + array[i] = entitlementDef.name; + break; + } + } + } + return array; + } + + public void LaunchPlatformShop(EntitlementDef entitlementDef) + { + throw new NotImplementedException(); + } + + public void LaunchPlatformShopAllProducts() + { + throw new NotImplementedException(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementAbstractions.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementAbstractions.cs new file mode 100644 index 0000000..507d9b3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementAbstractions.cs @@ -0,0 +1,37 @@ +using Facepunch.Steamworks; +using RoR2.Networking; + +namespace RoR2.EntitlementManagement; + +public static class EntitlementAbstractions +{ + public enum LoggedInPlatform + { + NONE_ERROR, + STEAMWORKS, + EPIC_ONLINE_SERVICES + } + + public static LoggedInPlatform loggedInPlatform; + + public static bool VerifyLocalSteamUser(EntitlementDef entitlementDef) + { + return Client.Instance.App.IsDlcInstalled(entitlementDef.steamAppId); + } + + public static bool VerifyRemoteUser(ClientAuthData authData, EntitlementDef entitlementDef) + { + for (int i = 0; i < authData.entitlements.Length; i++) + { + if (authData.entitlements[i].Equals(entitlementDef.name)) + { + return true; + } + } + return false; + } + + public static void OpenShopPage(EntitlementDef entitlementDef) + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementCatalog.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementCatalog.cs new file mode 100644 index 0000000..dcf8650 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementCatalog.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using HG; +using JetBrains.Annotations; +using RoR2.ContentManagement; + +namespace RoR2.EntitlementManagement; + +public static class EntitlementCatalog +{ + private static EntitlementDef[] _entitlementDefs = Array.Empty(); + + private static Dictionary nameToIndex = new Dictionary(); + + private static string[] indexToName = Array.Empty(); + + public static ReadOnlyArray entitlementDefs => _entitlementDefs; + + [SystemInitializer(new Type[] { })] + private static void Init() + { + SetEntitlementDefs(ContentManager.entitlementDefs); + } + + private static void SetEntitlementDefs(EntitlementDef[] newEntitlementDefs) + { + _entitlementDefs = ArrayUtils.Clone(newEntitlementDefs); + nameToIndex.Clear(); + Array.Resize(ref indexToName, newEntitlementDefs.Length); + for (int i = 0; i < entitlementDefs.Length; i++) + { + _entitlementDefs[i].entitlementIndex = (EntitlementIndex)i; + string name = _entitlementDefs[i].name; + nameToIndex[name] = (EntitlementIndex)i; + indexToName[i] = name; + } + } + + public static EntitlementIndex FindEntitlementIndex([NotNull] string entitlementName) + { + if (nameToIndex.TryGetValue(entitlementName, out var value)) + { + return value; + } + return EntitlementIndex.None; + } + + public static EntitlementDef GetEntitlementDef(EntitlementIndex entitlementIndex) + { + return ArrayUtils.GetSafe(_entitlementDefs, (int)entitlementIndex); + } + + [ConCommand(commandName = "entitlements_list", flags = ConVarFlags.None, helpText = "Displays all registered entitlements.")] + private static void CCEntitlementsList(ConCommandArgs args) + { + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + for (int i = 0; i < indexToName.Length; i++) + { + stringBuilder.AppendLine(indexToName[i]); + } + args.Log(stringBuilder.ToString()); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementDef.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementDef.cs new file mode 100644 index 0000000..0b7dff2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementDef.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace RoR2.EntitlementManagement; + +[CreateAssetMenu(menuName = "RoR2/EntitlementDef")] +public class EntitlementDef : ScriptableObject +{ + [HideInInspector] + [SerializeField] + public EntitlementIndex entitlementIndex = EntitlementIndex.None; + + [Tooltip("The localization token of the display name.")] + public string nameToken; + + [Header("PC")] + public uint steamAppId; + + [Tooltip("This is an EOS Item Id, not Offer Id.")] + public string eosItemId; + + [Header("XBox")] + public string GamecoreID; + + [Header("Playstation")] + public string SonyID; + + [Header("Nintendo")] + public ulong switchNsUid; + + [Tooltip("Nintendo DLC is an index. ie first DLC is 0, etc")] + public uint switchDLCIndex; + + private void OnDisable() + { + entitlementIndex = EntitlementIndex.None; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementIndex.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementIndex.cs new file mode 100644 index 0000000..aba7f33 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementIndex.cs @@ -0,0 +1,6 @@ +namespace RoR2.EntitlementManagement; + +public enum EntitlementIndex +{ + None = -1 +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementManager.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementManager.cs new file mode 100644 index 0000000..9f40c2e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/EntitlementManager.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Text; +using HG; + +namespace RoR2.EntitlementManagement; + +public static class EntitlementManager +{ + private static IUserEntitlementResolver[] localUserEntitlementResolvers = Array.Empty>(); + + private static IUserEntitlementResolver[] networkUserEntitlementResolvers = Array.Empty>(); + + private static bool isLoaded = true; + + private static bool collectLocalUserEntitlementResolversLocked = false; + + private static bool collectNetworkUserEntitlementResolversLocked; + + public static LocalUserEntitlementTracker localUserEntitlementTracker { get; private set; } + + public static NetworkUserServerEntitlementTracker networkUserEntitlementTracker { get; private set; } + + private static event Action>> _collectLocalUserEntitlementResolvers; + + public static event Action>> collectLocalUserEntitlementResolvers + { + add + { + if (collectLocalUserEntitlementResolversLocked) + { + throw new InvalidOperationException("collectLocalUserEntitlementResolvers has already been invoked. It is too late to add additional subscribers."); + } + _collectLocalUserEntitlementResolvers += value; + } + remove + { + _collectLocalUserEntitlementResolvers -= value; + } + } + + private static event Action>> _collectNetworkUserEntitlementResolvers; + + public static event Action>> collectNetworkUserEntitlementResolvers + { + add + { + if (collectNetworkUserEntitlementResolversLocked) + { + throw new InvalidOperationException("collectNetworkUserEntitlementResolvers has already been invoked. It is too late to add additional subscribers."); + } + _collectNetworkUserEntitlementResolvers += value; + } + remove + { + _collectNetworkUserEntitlementResolvers -= value; + } + } + + public static event Action onEntitlementsUpdated; + + [SystemInitializer(new Type[] { })] + private static void Init() + { + List> list = new List>(); + collectLocalUserEntitlementResolversLocked = true; + EntitlementManager._collectLocalUserEntitlementResolvers?.Invoke(list.Add); + EntitlementManager._collectLocalUserEntitlementResolvers = null; + List> list2 = new List>(); + collectNetworkUserEntitlementResolversLocked = true; + EntitlementManager._collectNetworkUserEntitlementResolvers?.Invoke(list2.Add); + EntitlementManager._collectNetworkUserEntitlementResolvers = null; + localUserEntitlementResolvers = list.ToArray(); + networkUserEntitlementResolvers = list2.ToArray(); + localUserEntitlementTracker = new LocalUserEntitlementTracker(localUserEntitlementResolvers); + networkUserEntitlementTracker = new NetworkUserServerEntitlementTracker(networkUserEntitlementResolvers); + } + + public static void NotifyEntitlementsUpdated() + { + EntitlementManager.onEntitlementsUpdated?.Invoke(); + } + + [ConCommand(commandName = "entitlement_check_local", flags = ConVarFlags.None, helpText = "Displays the availability of all entitlements for the sender.")] + private static void CCEntitlementCheckLocal(ConCommandArgs args) + { + LocalUser senderLocalUser = args.GetSenderLocalUser(); + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + foreach (EntitlementDef entitlementDef in EntitlementCatalog.entitlementDefs) + { + stringBuilder.Append(entitlementDef.name).Append("=").Append(localUserEntitlementTracker.UserHasEntitlement(senderLocalUser, entitlementDef)) + .AppendLine(); + } + args.Log(stringBuilder.ToString()); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } + + [ConCommand(commandName = "entitlement_force_refresh", flags = ConVarFlags.None, helpText = "Forces the entitlement trackers to refresh.")] + private static void CCEntitlementForceRefresh(ConCommandArgs args) + { + localUserEntitlementTracker.UpdateAllUserEntitlements(); + networkUserEntitlementTracker.UpdateAllUserEntitlements(); + NotifyEntitlementsUpdated(); + } + + public static void UpdateLocalUsersEntitlements() + { + localUserEntitlementTracker.UpdateAllUserEntitlements(); + NotifyEntitlementsUpdated(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/IPlatformShopLauncher.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/IPlatformShopLauncher.cs new file mode 100644 index 0000000..56ae6d3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/IPlatformShopLauncher.cs @@ -0,0 +1,12 @@ +using System; + +namespace RoR2.EntitlementManagement; + +public interface IPlatformShopLauncher +{ + event Action OnPlatformShopClosed; + + void LaunchPlatformShop(EntitlementDef entitlementDef); + + void LaunchPlatformShopAllProducts(); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/IUserEntitlementResolver.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/IUserEntitlementResolver.cs new file mode 100644 index 0000000..e923e1f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/IUserEntitlementResolver.cs @@ -0,0 +1,11 @@ +using System; +using JetBrains.Annotations; + +namespace RoR2.EntitlementManagement; + +public interface IUserEntitlementResolver where TUser : class +{ + event Action onEntitlementsChanged; + + bool CheckUserHasEntitlement([NotNull] TUser user, [NotNull] EntitlementDef entitlementDef); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/LocalUserEntitlementTracker.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/LocalUserEntitlementTracker.cs new file mode 100644 index 0000000..3143a07 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/LocalUserEntitlementTracker.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace RoR2.EntitlementManagement; + +public class LocalUserEntitlementTracker : BaseUserEntitlementTracker, IDisposable +{ + protected override void SubscribeToUserDiscovered() + { + LocalUserManager.onUserSignIn += OnUserDiscovered; + } + + protected override void SubscribeToUserLost() + { + LocalUserManager.onUserSignOut += OnUserLost; + } + + protected override void UnsubscribeFromUserDiscovered() + { + LocalUserManager.onUserSignIn -= OnUserDiscovered; + } + + protected override void UnsubscribeFromUserLost() + { + LocalUserManager.onUserSignOut -= OnUserLost; + } + + protected override IList GetCurrentUsers() + { + return LocalUserManager.readOnlyLocalUsersList; + } + + public LocalUserEntitlementTracker([NotNull] IUserEntitlementResolver[] entitlementResolvers) + : base(entitlementResolvers) + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/NetworkUserServerEntitlementTracker.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/NetworkUserServerEntitlementTracker.cs new file mode 100644 index 0000000..6da1aa3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/NetworkUserServerEntitlementTracker.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using UnityEngine.Networking; + +namespace RoR2.EntitlementManagement; + +public class NetworkUserServerEntitlementTracker : BaseUserEntitlementTracker, IDisposable +{ + protected override void SubscribeToUserDiscovered() + { + NetworkUser.onNetworkUserDiscovered += OnUserDiscovered; + } + + protected override void SubscribeToUserLost() + { + NetworkUser.onNetworkUserLost += OnUserLost; + } + + protected override void UnsubscribeFromUserDiscovered() + { + NetworkUser.onNetworkUserDiscovered -= OnUserDiscovered; + } + + protected override void UnsubscribeFromUserLost() + { + NetworkUser.onNetworkUserLost -= OnUserLost; + } + + protected override IList GetCurrentUsers() + { + return NetworkUser.readOnlyInstancesList; + } + + public NetworkUserServerEntitlementTracker(IUserEntitlementResolver[] entitlementResolvers) + : base(entitlementResolvers) + { + NetworkUser.onPostNetworkUserStart += OnPostNetworkUserStart; + } + + private void OnPostNetworkUserStart(NetworkUser networkUser) + { + if (NetworkServer.active) + { + UpdateUserEntitlements(networkUser); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/SteamworksEntitlementResolver.cs b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/SteamworksEntitlementResolver.cs new file mode 100644 index 0000000..7b7c808 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntitlementManagement/SteamworksEntitlementResolver.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using Facepunch.Steamworks; +using JetBrains.Annotations; +using RoR2.ContentManagement; +using RoR2.Networking; + +namespace RoR2.EntitlementManagement; + +public class SteamworksEntitlementResolver : IUserEntitementsResolverNetworkAndLocal, IUserEntitlementResolver, IUserEntitlementResolver, IPlatformShopLauncher +{ + private static event Action onDlcInstalled; + + public event Action OnPlatformShopClosed; + + event Action IUserEntitlementResolver.onEntitlementsChanged + { + add + { + onDlcInstalled += value; + } + remove + { + onDlcInstalled -= value; + } + } + + event Action IUserEntitlementResolver.onEntitlementsChanged + { + add + { + } + remove + { + } + } + + private static void OnDlcInstalled(uint appId) + { + SteamworksEntitlementResolver.onDlcInstalled?.Invoke(); + } + + bool IUserEntitlementResolver.CheckUserHasEntitlement([NotNull] LocalUser localUser, [NotNull] EntitlementDef entitlementDef) + { + return EntitlementAbstractions.VerifyLocalSteamUser(entitlementDef); + } + + bool IUserEntitlementResolver.CheckUserHasEntitlement([NotNull] NetworkUser networkUser, [NotNull] EntitlementDef entitlementDef) + { + if (!networkUser) + { + return false; + } + if (networkUser.isLocalPlayer) + { + return EntitlementAbstractions.VerifyLocalSteamUser(entitlementDef); + } + ClientAuthData clientAuthData = ServerAuthManager.FindAuthData(networkUser.connectionToClient); + if (clientAuthData == null) + { + return false; + } + PlatformID platformId = clientAuthData.platformId; + if (!platformId.isValid) + { + return false; + } + return EntitlementAbstractions.VerifyRemoteUser(clientAuthData, entitlementDef); + } + + public SteamworksEntitlementResolver() + { + EntitlementManager.collectLocalUserEntitlementResolvers += delegate(Action> add) + { + add(this); + }; + EntitlementManager.collectNetworkUserEntitlementResolvers += delegate(Action> add) + { + add(this); + }; + SteamworksClientManager.onLoaded += delegate + { + SteamworksClientManager.instance.steamworksClient.App.OnDlcInstalled += OnDlcInstalled; + }; + } + + public string[] BuildEntitlements() + { + List list = new List(); + EntitlementDef[] entitlementDefs = ContentManager.entitlementDefs; + foreach (EntitlementDef entitlementDef in entitlementDefs) + { + if (Client.Instance.App.IsDlcInstalled(entitlementDef.steamAppId)) + { + list.Add(entitlementDef.name); + } + } + return list.ToArray(); + } + + public void LaunchPlatformShop(EntitlementDef entitlementDef) + { + throw new NotImplementedException(); + } + + public void LaunchPlatformShopAllProducts() + { + throw new NotImplementedException(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/BoolEventSplitter.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/BoolEventSplitter.cs new file mode 100644 index 0000000..c52c325 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/BoolEventSplitter.cs @@ -0,0 +1,16 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class BoolEventSplitter : MonoBehaviour +{ + public UnityEvent trueEvent; + + public UnityEvent falseEvent; + + public void CallEvent(bool value) + { + (value ? trueEvent : falseEvent)?.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Counter.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Counter.cs new file mode 100644 index 0000000..fa8f692 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Counter.cs @@ -0,0 +1,27 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class Counter : MonoBehaviour +{ + public int value; + + public int threshold; + + public UnityEvent onTrigger; + + public void Add(int valueToAdd) + { + value += valueToAdd; + if (value >= threshold) + { + onTrigger.Invoke(); + } + } + + public void SetValue(int newValue) + { + value = newValue; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/DelayedEvent.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/DelayedEvent.cs new file mode 100644 index 0000000..3c7dacc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/DelayedEvent.cs @@ -0,0 +1,52 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class DelayedEvent : MonoBehaviour +{ + public enum TimeStepType + { + Time, + UnscaledTime, + FixedTime + } + + public UnityEvent action; + + public TimeStepType timeStepType; + + public void CallDelayed(float timer) + { + TimerQueue timerQueue = null; + switch (timeStepType) + { + case TimeStepType.Time: + timerQueue = RoR2Application.timeTimers; + break; + case TimeStepType.UnscaledTime: + timerQueue = RoR2Application.unscaledTimeTimers; + break; + case TimeStepType.FixedTime: + timerQueue = RoR2Application.fixedTimeTimers; + break; + } + timerQueue?.CreateTimer(timer, Call); + } + + public void CallDelayedIfActiveAndEnabled(float timer) + { + if (base.isActiveAndEnabled) + { + CallDelayed(timer); + } + } + + private void Call() + { + if ((bool)this && base.enabled) + { + action.Invoke(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Repeat.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Repeat.cs new file mode 100644 index 0000000..a8e5b5f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Repeat.cs @@ -0,0 +1,18 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class Repeat : MonoBehaviour +{ + public UnityEvent repeatedEvent; + + public void CallRepeat(int repeatNumber) + { + while (repeatNumber > 0) + { + repeatNumber--; + repeatedEvent?.Invoke(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/TeleporterEventRelay.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/TeleporterEventRelay.cs new file mode 100644 index 0000000..a87dc41 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/TeleporterEventRelay.cs @@ -0,0 +1,59 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class TeleporterEventRelay : MonoBehaviour +{ + public UnityEvent onTeleporterBeginCharging; + + public UnityEvent onTeleporterCharged; + + public UnityEvent onTeleporterFinish; + + private TeleporterInteraction.ActivationState recordedActivationState; + + public void OnEnable() + { + TeleporterInteraction.onTeleporterBeginChargingGlobal += CheckTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal += CheckTeleporterCharged; + TeleporterInteraction.onTeleporterFinishGlobal += CheckTeleporterFinish; + CheckTeleporterBeginCharging(TeleporterInteraction.instance); + CheckTeleporterCharged(TeleporterInteraction.instance); + CheckTeleporterFinish(TeleporterInteraction.instance); + } + + public void OnDisable() + { + TeleporterInteraction.onTeleporterBeginChargingGlobal -= CheckTeleporterBeginCharging; + TeleporterInteraction.onTeleporterChargedGlobal -= CheckTeleporterCharged; + TeleporterInteraction.onTeleporterFinishGlobal -= CheckTeleporterFinish; + } + + private void CheckTeleporterBeginCharging(TeleporterInteraction teleporter) + { + if ((bool)teleporter && teleporter.activationState >= TeleporterInteraction.ActivationState.Charging && recordedActivationState < TeleporterInteraction.ActivationState.Charging) + { + onTeleporterBeginCharging?.Invoke(); + recordedActivationState = TeleporterInteraction.ActivationState.Charging; + } + } + + private void CheckTeleporterCharged(TeleporterInteraction teleporter) + { + if ((bool)teleporter && teleporter.activationState >= TeleporterInteraction.ActivationState.Charged && recordedActivationState < TeleporterInteraction.ActivationState.Charged) + { + onTeleporterCharged?.Invoke(); + recordedActivationState = TeleporterInteraction.ActivationState.Charged; + } + } + + private void CheckTeleporterFinish(TeleporterInteraction teleporter) + { + if ((bool)teleporter && teleporter.activationState >= TeleporterInteraction.ActivationState.Finished && recordedActivationState < TeleporterInteraction.ActivationState.Finished) + { + onTeleporterFinish?.Invoke(); + recordedActivationState = TeleporterInteraction.ActivationState.Finished; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Timer.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Timer.cs new file mode 100644 index 0000000..47ebfe1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/Timer.cs @@ -0,0 +1,150 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class Timer : MonoBehaviour +{ + public enum TimeStepType + { + Time, + UnscaledTime, + FixedTime + } + + [SerializeField] + private float _duration; + + [SerializeField] + private TimeStepType _timeStepType = TimeStepType.FixedTime; + + public bool resetTimerOnEnable = true; + + public bool playTimerOnEnable = true; + + public bool loop; + + public UnityEvent action; + + private float stopwatch; + + private bool timerRunning; + + public float duration + { + get + { + return _duration; + } + set + { + _duration = value; + } + } + + public TimeStepType timeStepType + { + get + { + return _timeStepType; + } + set + { + _timeStepType = value; + } + } + + private void OnEnable() + { + if (resetTimerOnEnable) + { + RewindTimerToBeginning(); + } + if (playTimerOnEnable) + { + PlayTimer(); + } + } + + private void Update() + { + if (timerRunning) + { + if (timeStepType == TimeStepType.Time) + { + RunTimer(Time.deltaTime); + } + else if (timeStepType == TimeStepType.UnscaledTime) + { + RunTimer(Time.unscaledDeltaTime); + } + } + } + + private void FixedUpdate() + { + if (timerRunning && timeStepType == TimeStepType.FixedTime) + { + RunTimer(Time.fixedDeltaTime); + } + } + + public void RewindTimerToBeginning() + { + stopwatch = 0f; + } + + public void SkipTimerToEnd() + { + stopwatch = duration; + } + + public void SetTimerPlaying(bool newTimerRunning) + { + timerRunning = newTimerRunning; + } + + public void PlayTimer() + { + SetTimerPlaying(newTimerRunning: true); + } + + public void PauseTimer() + { + SetTimerPlaying(newTimerRunning: false); + } + + public void CancelTimer() + { + PauseTimer(); + RewindTimerToBeginning(); + } + + public void PlayTimerFromBeginning() + { + RewindTimerToBeginning(); + PlayTimer(); + } + + private void RunTimer(float deltaTime) + { + stopwatch += deltaTime; + if (stopwatch >= duration) + { + stopwatch = 0f; + try + { + action?.Invoke(); + } + catch (Exception message) + { + Debug.LogError(message); + } + if (!loop) + { + timerRunning = false; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.EntityLogic/UpdateEvent.cs b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/UpdateEvent.cs new file mode 100644 index 0000000..f34327c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.EntityLogic/UpdateEvent.cs @@ -0,0 +1,32 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.EntityLogic; + +public class UpdateEvent : MonoBehaviour +{ + [Tooltip("Don't call the action until at least this many updates have fired")] + [SerializeField] + private int updateSkipCount; + + [Tooltip("Don't call the action after this many updates have fired. If negative, ignore.")] + [SerializeField] + private int maxInvokeCount = -1; + + [SerializeField] + private UnityEvent action; + + private int invokeCount; + + private int updateCount; + + private void Update() + { + if (updateSkipCount < updateCount && (maxInvokeCount < 0 || invokeCount < maxInvokeCount)) + { + action?.Invoke(); + invokeCount++; + } + updateCount++; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionCatalog.cs b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionCatalog.cs new file mode 100644 index 0000000..ac3db02 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionCatalog.cs @@ -0,0 +1,27 @@ +using System; +using HG; +using RoR2.ContentManagement; + +namespace RoR2.ExpansionManagement; + +public static class ExpansionCatalog +{ + private static ExpansionDef[] _expansionDefs = Array.Empty(); + + public static ReadOnlyArray expansionDefs => _expansionDefs; + + private static void SetExpansions(ExpansionDef[] newExpansionsDefs) + { + ArrayUtils.CloneTo(newExpansionsDefs, ref _expansionDefs); + for (int i = 0; i < _expansionDefs.Length; i++) + { + _expansionDefs[i].expansionIndex = (ExpansionIndex)i; + } + } + + [SystemInitializer(new Type[] { })] + private static void Init() + { + SetExpansions(ContentManager.expansionDefs); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionDef.cs b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionDef.cs new file mode 100644 index 0000000..7df0b33 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionDef.cs @@ -0,0 +1,34 @@ +using RoR2.EntitlementManagement; +using UnityEngine; + +namespace RoR2.ExpansionManagement; + +[CreateAssetMenu(menuName = "RoR2/ExpansionDef")] +public class ExpansionDef : ScriptableObject +{ + [SerializeField] + [HideInInspector] + public ExpansionIndex expansionIndex; + + [Tooltip("The entitlement required to use this expansion.")] + public EntitlementDef requiredEntitlement; + + [Tooltip("The token for the user-facing name of this expansion.")] + public string nameToken; + + [Tooltip("The token for the user-facing description of this expansion.")] + public string descriptionToken; + + [Tooltip("The icon for this expansion.")] + [ShowThumbnail] + public Sprite iconSprite; + + [Tooltip("The icon to display when this expansion is disabled.")] + [ShowThumbnail] + public Sprite disabledIconSprite; + + public RuleChoiceDef enabledChoice; + + [Tooltip("This prefab is instantiated and childed to the run")] + public GameObject runBehaviorPrefab; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionIndex.cs b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionIndex.cs new file mode 100644 index 0000000..e478c7c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionIndex.cs @@ -0,0 +1,6 @@ +namespace RoR2.ExpansionManagement; + +public enum ExpansionIndex +{ + None = -1 +} diff --git a/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionRequirementComponent.cs b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionRequirementComponent.cs new file mode 100644 index 0000000..de45d0e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.ExpansionManagement/ExpansionRequirementComponent.cs @@ -0,0 +1,66 @@ +using RoR2.EntitlementManagement; +using UnityEngine; + +namespace RoR2.ExpansionManagement; + +public class ExpansionRequirementComponent : MonoBehaviour +{ + public ExpansionDef requiredExpansion; + + public bool requireEntitlementIfPlayerControlled; + + public static bool ignoreExpansionDisablingForPlayerControlled = true; + + private void Start() + { + CharacterBody component = GetComponent(); + if ((bool)component && component.isPlayerControlled && !PlayerCanUseBody(component.master.playerCharacterMasterController)) + { + Object.Destroy(base.gameObject); + } + } + + public bool IgnoreExpansionDisabling() + { + if (requireEntitlementIfPlayerControlled) + { + return ignoreExpansionDisablingForPlayerControlled; + } + return false; + } + + public bool PlayerCanUseBody(PlayerCharacterMasterController playerCharacterMasterController) + { + Run instance = Run.instance; + if (!instance) + { + return false; + } + if ((bool)requiredExpansion) + { + if (!instance.IsExpansionEnabled(requiredExpansion) && !IgnoreExpansionDisabling()) + { + return false; + } + if (requireEntitlementIfPlayerControlled) + { + EntitlementDef requiredEntitlement = requiredExpansion.requiredEntitlement; + if ((bool)requiredEntitlement) + { + PlayerCharacterMasterControllerEntitlementTracker component = playerCharacterMasterController.GetComponent(); + if (!component) + { + Debug.LogWarning("Rejecting body because the playerCharacterMasterController doesn't have a sibling PlayerCharacterMasterControllerEntitlementTracker"); + return false; + } + if (!component.HasEntitlement(requiredEntitlement)) + { + Debug.LogWarning("Rejecting body because the player doesn't have entitlement " + requiredEntitlement.name); + return false; + } + } + } + } + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Gamecore/GamecoreEngagementScreen.cs b/ilspy_dump/ror2_csproj/RoR2.Gamecore/GamecoreEngagementScreen.cs new file mode 100644 index 0000000..0ce22bc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Gamecore/GamecoreEngagementScreen.cs @@ -0,0 +1,9 @@ +using RoR2.UI.MainMenu; +using UnityEngine; + +namespace RoR2.Gamecore; + +public class GamecoreEngagementScreen : MonoBehaviour +{ + public MainMenuController Menu; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/DefaultGamepadVibrationController.cs b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/DefaultGamepadVibrationController.cs new file mode 100644 index 0000000..ac817e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/DefaultGamepadVibrationController.cs @@ -0,0 +1,12 @@ +using HG; + +namespace RoR2.GamepadVibration; + +public class DefaultGamepadVibrationController : GamepadVibrationController +{ + protected override void CalculateMotorValues(in VibrationContext vibrationContext, float[] motorValues) + { + float value = vibrationContext.CalcCamDisplacementMagnitude(); + ArrayUtils.SetRange(motorValues, in value, 0, motorValues.Length); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationController.cs b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationController.cs new file mode 100644 index 0000000..d3e300a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationController.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using HG.Reflection; +using Rewired; +using UnityEngine; + +namespace RoR2.GamepadVibration; + +public abstract class GamepadVibrationController : IDisposable +{ + private Joystick _joystick; + + private float[] motorValues = Array.Empty(); + + private static List<(Func predicate, Type vibrationControllerType)> vibrationControllerTypeResolver = new List<(Func, Type)>(); + + private static Type defaultVibrationControllerType = typeof(DefaultGamepadVibrationController); + + public Joystick joystick + { + get + { + return _joystick; + } + private set + { + if (_joystick != value) + { + _joystick = value; + if (_joystick != null) + { + Array.Resize(ref motorValues, _joystick.vibrationMotorCount); + OnJoystickAssigned(_joystick); + } + } + } + } + + protected virtual void OnJoystickAssigned(Joystick joystick) + { + } + + public void Dispose() + { + StopVibration(); + DisposeInternal(); + joystick = null; + } + + protected virtual void DisposeInternal() + { + } + + public void ApplyVibration(in VibrationContext vibrationContext) + { + Array.Clear(motorValues, 0, motorValues.Length); + try + { + CalculateMotorValues(in vibrationContext, motorValues); + } + catch (Exception message) + { + Debug.LogError(message); + } + float userVibrationScale = vibrationContext.userVibrationScale; + for (int i = 0; i < motorValues.Length; i++) + { + joystick.SetVibration(i, motorValues[i] * userVibrationScale); + } + try + { + ApplyNonStandardVibration(in vibrationContext); + } + catch (Exception message2) + { + Debug.LogError(message2); + } + } + + protected virtual void CalculateMotorValues(in VibrationContext vibrationContext, float[] motorValues) + { + } + + protected virtual void ApplyNonStandardVibration(in VibrationContext vibrationContext) + { + } + + public void StopVibration() + { + try + { + StopNonStandardVibration(); + } + catch (Exception message) + { + Debug.LogError(message); + } + joystick.StopVibration(); + } + + protected virtual void StopNonStandardVibration() + { + } + + public static GamepadVibrationController Create(Joystick joystick) + { + Type item = defaultVibrationControllerType; + for (int i = 0; i < vibrationControllerTypeResolver.Count; i++) + { + try + { + (Func, Type) tuple = vibrationControllerTypeResolver[i]; + if (tuple.Item1(joystick)) + { + item = tuple.Item2; + break; + } + } + catch (Exception message) + { + Debug.LogError(message); + } + } + GamepadVibrationController obj = (GamepadVibrationController)Activator.CreateInstance(item); + obj.joystick = joystick; + return obj; + } + + public static void RegisterResolver(Func predicate, Type vibrationControllerType) + { + predicate = predicate ?? throw new ArgumentNullException("predicate"); + vibrationControllerType = vibrationControllerType ?? throw new ArgumentNullException("vibrationControllerType"); + if (!vibrationControllerType.IsSubclassOf(typeof(GamepadVibrationController))) + { + throw new ArgumentException("vibrationControllerType must inherit from GamepadVibrationController"); + } + vibrationControllerTypeResolver.Add((predicate, vibrationControllerType)); + } + + [SystemInitializer(new Type[] { })] + private static void Init() + { + List list = new List(); + HG.Reflection.SearchableAttribute.GetInstances(list); + foreach (GamepadVibrationControllerResolverAttribute item in list) + { + try + { + MethodInfo methodInfo = (MethodInfo)item.target; + if (!methodInfo.IsStatic) + { + throw new Exception("GamepadVibrationControllerResolverAttribute target must be a static method. target=" + methodInfo.DeclaringType.FullName + "." + methodInfo.Name); + } + RegisterResolver((Func)methodInfo.CreateDelegate(typeof(Func)), item.vibrationControllerType); + } + catch (Exception message) + { + Debug.LogError(message); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationControllerResolverAttribute.cs b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationControllerResolverAttribute.cs new file mode 100644 index 0000000..535f480 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationControllerResolverAttribute.cs @@ -0,0 +1,15 @@ +using System; +using HG.Reflection; + +namespace RoR2.GamepadVibration; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] +public class GamepadVibrationControllerResolverAttribute : HG.Reflection.SearchableAttribute +{ + public readonly Type vibrationControllerType; + + public GamepadVibrationControllerResolverAttribute(Type vibrationControllerType) + { + this.vibrationControllerType = vibrationControllerType; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationManager.cs b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationManager.cs new file mode 100644 index 0000000..a53081f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/GamepadVibrationManager.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using HG; +using HG.Collections.Generic; +using Rewired; +using RoR2.UI; +using UnityEngine; + +namespace RoR2.GamepadVibration; + +public static class GamepadVibrationManager +{ + private static readonly AssociationList joystickToVibrationController = new AssociationList(4); + + private static int[] joystickIndexToLocalUserIndex = new int[4]; + + [SystemInitializer(new Type[] { typeof(GamepadVibrationController) })] + private static void Init() + { + RoR2Application.onUpdate += Update; + ReInput.ControllerConnectedEvent += OnControllerConnected; + ReInput.ControllerPreDisconnectEvent += OnControllerPreDisconnect; + RoR2Application.onShutDown = (Action)Delegate.Combine(RoR2Application.onShutDown, new Action(OnApplicationShutDown)); + foreach (Controller controller in ReInput.controllers.Controllers) + { + OnControllerConnected(new ControllerStatusChangedEventArgs(controller.name, controller.id, controller.type)); + } + } + + private static void OnControllerConnected(ControllerStatusChangedEventArgs args) + { + if (args.controller is Joystick joystick) + { + joystickToVibrationController.Add(joystick, GamepadVibrationController.Create(joystick)); + } + } + + private static void OnControllerPreDisconnect(ControllerStatusChangedEventArgs args) + { + if (args.controller is Joystick key) + { + int num = joystickToVibrationController.FindKeyIndex(key); + if (num >= 0) + { + joystickToVibrationController[num].Value.Dispose(); + joystickToVibrationController.RemoveAt(num); + } + } + } + + private static void OnApplicationShutDown() + { + for (int num = joystickToVibrationController.Count - 1; num >= 0; num--) + { + joystickToVibrationController[num].Value.Dispose(); + joystickToVibrationController.RemoveAt(num); + } + } + + private static void Update() + { + if (Time.deltaTime <= 0f) + { + foreach (KeyValuePair item in joystickToVibrationController) + { + item.Value.StopVibration(); + } + return; + } + ReadOnlyCollection readOnlyLocalUsersList = LocalUserManager.readOnlyLocalUsersList; + ArrayUtils.EnsureCapacity(ref joystickIndexToLocalUserIndex, joystickToVibrationController.Count); + int[] array = joystickIndexToLocalUserIndex; + int value = -1; + ArrayUtils.SetRange(array, in value, 0, joystickToVibrationController.Count); + for (int i = 0; i < readOnlyLocalUsersList.Count; i++) + { + LocalUser localUser = readOnlyLocalUsersList[i]; + if (localUser.inputPlayer != null && (bool)localUser.eventSystem && localUser.eventSystem.currentInputSource == MPEventSystem.InputSource.Gamepad && localUser.inputPlayer?.controllers.GetLastActiveController() is Joystick key) + { + int num = joystickToVibrationController.FindKeyIndex(key); + if (num >= 0) + { + joystickIndexToLocalUserIndex[num] = i; + } + } + } + for (int j = 0; j < joystickToVibrationController.Count; j++) + { + GamepadVibrationController value2 = joystickToVibrationController[j].Value; + int num2 = joystickIndexToLocalUserIndex[j]; + LocalUser localUser2 = ((num2 >= 0) ? readOnlyLocalUsersList[num2] : null); + if (localUser2 != null && localUser2.userProfile != null) + { + VibrationContext vibrationContext = default(VibrationContext); + vibrationContext.localUser = localUser2; + vibrationContext.cameraRigController = localUser2.cameraRigController; + vibrationContext.userVibrationScale = localUser2.userProfile.gamepadVibrationScale; + VibrationContext vibrationContext2 = vibrationContext; + value2.ApplyVibration(in vibrationContext2); + } + else + { + value2.StopVibration(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/VibrationContext.cs b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/VibrationContext.cs new file mode 100644 index 0000000..d81cb01 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/VibrationContext.cs @@ -0,0 +1,19 @@ +namespace RoR2.GamepadVibration; + +public struct VibrationContext +{ + public CameraRigController cameraRigController; + + public LocalUser localUser; + + public float userVibrationScale; + + public float CalcCamDisplacementMagnitude() + { + if (!cameraRigController || !Run.instance || !Run.instance.isRunning || localUser.cachedMasterController.master.lostBodyToDeath) + { + return 0f; + } + return cameraRigController.rawScreenShakeDisplacement.magnitude; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/Xbox360GamepadVibrationController.cs b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/Xbox360GamepadVibrationController.cs new file mode 100644 index 0000000..d43ab26 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.GamepadVibration/Xbox360GamepadVibrationController.cs @@ -0,0 +1,31 @@ +using Rewired; + +namespace RoR2.GamepadVibration; + +public class Xbox360GamepadVibrationController : GamepadVibrationController +{ + protected static readonly float deepRumbleFactor = 5f; + + protected override void CalculateMotorValues(in VibrationContext vibrationContext, float[] motorValues) + { + float num = vibrationContext.CalcCamDisplacementMagnitude(); + float num2 = num / deepRumbleFactor; + float num3 = num; + motorValues[0] = num2; + motorValues[1] = num3; + } + + [GamepadVibrationControllerResolver(typeof(Xbox360GamepadVibrationController))] + private static bool Resolve(Joystick joystick) + { + if (joystick.vibrationMotorCount >= 2) + { + if (!joystick.name.Contains("Xbox")) + { + return joystick.name.Contains("XInput Gamepad "); + } + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Hologram/HologramProjector.cs b/ilspy_dump/ror2_csproj/RoR2.Hologram/HologramProjector.cs new file mode 100644 index 0000000..7ea92ef --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Hologram/HologramProjector.cs @@ -0,0 +1,182 @@ +using System.Collections.ObjectModel; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Hologram; + +public class HologramProjector : MonoBehaviour +{ + [Tooltip("The range in meters at which the hologram begins to display.")] + public float displayDistance = 15f; + + [Tooltip("The position at which to display the hologram.")] + public Transform hologramPivot; + + [Tooltip("Whether or not the hologram will pivot to the player")] + public bool disableHologramRotation; + + private float transformDampVelocity; + + private IHologramContentProvider contentProvider; + + private float viewerReselectTimer; + + private float viewerReselectInterval = 0.25f; + + private Transform cachedViewer; + + private CharacterBody cachedViewerBody; + + private NetworkInstanceId cachedViewerObjectId; + + private NetworkIdentity cachedNetworkIdentity; + + public GameObject hologramContentInstance; + + private Transform viewerTransform; + + private CharacterBody viewerBody; + + private void Awake() + { + contentProvider = GetComponent(); + cachedNetworkIdentity = GetComponent(); + } + + private Transform FindViewer(Vector3 position) + { + if (viewerReselectTimer > 0f) + { + return cachedViewer; + } + viewerReselectTimer = viewerReselectInterval; + cachedViewer = null; + float num = float.PositiveInfinity; + ReadOnlyCollection instances = PlayerCharacterMasterController.instances; + int i = 0; + for (int count = instances.Count; i < count; i++) + { + GameObject bodyObject = instances[i].master.GetBodyObject(); + if ((bool)bodyObject) + { + float sqrMagnitude = (bodyObject.transform.position - position).sqrMagnitude; + if (sqrMagnitude < num) + { + num = sqrMagnitude; + cachedViewer = bodyObject.transform; + cachedViewerBody = bodyObject.GetComponent(); + } + } + } + return cachedViewer; + } + + private void CacheViewerBody(Transform _viewer) + { + if (!(_viewer == null) && (!viewerBody || !(viewerTransform == _viewer)) && _viewer.TryGetComponent(out var component)) + { + viewerTransform = _viewer; + viewerBody = component; + } + } + + public Vector3 GetHologramPivotPosition() + { + if (!hologramPivot) + { + return base.transform.position; + } + return hologramPivot.position; + } + + public CharacterBody GetCachedViewerBody() + { + return cachedViewerBody; + } + + public NetworkInstanceId GetCachedViewerObjectId() + { + return cachedViewerObjectId; + } + + public void UpdateForViewer(Transform viewer, Vector3 pivotPosition) + { + bool flag = false; + Vector3 vector = (viewer ? viewer.position : base.transform.position); + Vector3 forward = Vector3.zero; + if ((bool)viewer) + { + forward = pivotPosition - vector; + if (forward.sqrMagnitude <= displayDistance * displayDistance) + { + flag = true; + } + } + if (flag) + { + flag = contentProvider.ShouldDisplayHologram(viewer.gameObject); + } + if (flag) + { + if (!hologramContentInstance) + { + BuildHologram(); + } + if ((bool)hologramContentInstance && contentProvider != null) + { + contentProvider.UpdateHologramContent(hologramContentInstance, viewer); + if (!disableHologramRotation) + { + hologramContentInstance.transform.rotation = Util.SmoothDampQuaternion(hologramContentInstance.transform.rotation, Util.QuaternionSafeLookRotation(forward), ref transformDampVelocity, 0.2f); + } + } + } + else + { + DestroyHologram(); + } + } + + private void Update() + { + viewerReselectTimer -= Time.deltaTime; + Vector3 hologramPivotPosition = GetHologramPivotPosition(); + Transform viewer = FindViewer(hologramPivotPosition); + UpdateForViewer(viewer, hologramPivotPosition); + } + + private void BuildHologram() + { + DestroyHologram(); + if (contentProvider == null) + { + return; + } + GameObject hologramContentPrefab = contentProvider.GetHologramContentPrefab(); + if ((bool)hologramContentPrefab) + { + hologramContentInstance = Object.Instantiate(hologramContentPrefab); + hologramContentInstance.transform.parent = (hologramPivot ? hologramPivot : base.transform); + hologramContentInstance.transform.localPosition = Vector3.zero; + hologramContentInstance.transform.localRotation = Quaternion.identity; + hologramContentInstance.transform.localScale = Vector3.one; + if ((bool)viewerTransform && !disableHologramRotation) + { + Vector3 obj = (hologramPivot ? hologramPivot.position : base.transform.position); + _ = viewerTransform.position; + Vector3 forward = obj - viewerTransform.position; + hologramContentInstance.transform.rotation = Util.QuaternionSafeLookRotation(forward); + } + contentProvider.UpdateHologramContent(hologramContentInstance, viewerTransform); + } + } + + private void DestroyHologram() + { + if ((bool)hologramContentInstance) + { + Object.Destroy(hologramContentInstance); + } + hologramContentInstance = null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.HudOverlay/HudOverlayManager.cs b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/HudOverlayManager.cs new file mode 100644 index 0000000..fdfd42d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/HudOverlayManager.cs @@ -0,0 +1,102 @@ +using System.Collections.Generic; +using HG; +using UnityEngine; + +namespace RoR2.HudOverlay; + +public static class HudOverlayManager +{ + private static Dictionary targetToTargetTracker = new Dictionary(); + + private static List globalOverlays = new List(); + + public static OverlayController AddOverlay(GameObject target, OverlayCreationParams overlayCreationParams) + { + if (target != null) + { + TargetTracker andIncrementTargetTracker = GetAndIncrementTargetTracker(target); + OverlayController overlayController = new OverlayController(andIncrementTargetTracker, overlayCreationParams); + andIncrementTargetTracker.AddOverlay(overlayController); + return overlayController; + } + Debug.LogError("AddOverlay can't be called with no target--did you mean to use AddGlobalOverlay?"); + return null; + } + + public static void RemoveOverlay(OverlayController overlayController) + { + TargetTracker owner = overlayController.owner; + if (owner != null) + { + owner.RemoveOverlay(overlayController); + DecrementTargetTracker(owner); + } + else + { + Debug.LogError("RemoveOverlay can't be called on an OverlayController with no target--did you mean to use RemoveGlobalOverlay?"); + } + } + + public static OverlayController AddGlobalOverlay(OverlayCreationParams overlayCreationParams) + { + OverlayController overlayController = new OverlayController(null, overlayCreationParams); + globalOverlays.Add(overlayController); + return overlayController; + } + + public static void RemoveGlobalOverlay(OverlayController overlayController) + { + if (overlayController.owner == null) + { + globalOverlays.Remove(overlayController); + } + else + { + Debug.LogError("RemoveGlobalOverlay can't be called on an OverlayController with a target--did you mean to use RemoveOverlay?"); + } + } + + public static void GetGlobalOverlayControllers(List dest) + { + ListUtils.AddRange(dest, globalOverlays); + } + + private static TargetTracker GetAndIncrementTargetTracker(GameObject target) + { + if (!targetToTargetTracker.TryGetValue(target, out var value)) + { + value = CreateTargetTracker(target); + } + value.refCount++; + return value; + } + + private static void DecrementTargetTracker(TargetTracker targetTracker) + { + targetTracker.refCount--; + if (targetTracker.refCount <= 0) + { + targetToTargetTracker.Remove(targetTracker.target); + targetTracker.Dispose(); + } + } + + private static TargetTracker CreateTargetTracker(GameObject target) + { + TargetTracker targetTracker = new TargetTracker + { + target = target + }; + targetToTargetTracker.Add(target, targetTracker); + return targetTracker; + } + + public static TargetTracker GetTargetTracker(GameObject target) + { + if ((object)target != null && targetToTargetTracker.TryGetValue(target, out var value)) + { + return value; + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.HudOverlay/HudOverlayViewer.cs b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/HudOverlayViewer.cs new file mode 100644 index 0000000..1ae3cc4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/HudOverlayViewer.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using HG; +using HG.Collections.Generic; +using RoR2.UI; +using UnityEngine; + +namespace RoR2.HudOverlay; + +public class HudOverlayViewer : MonoBehaviour +{ + public HUD hud; + + public ChildLocator childLocator; + + private CameraRigController _cameraRigController; + + private GameObject _target; + + private AssociationList overlayControllerToInstance = new AssociationList(); + + private CameraRigController cameraRigController + { + get + { + return _cameraRigController; + } + set + { + if ((object)_cameraRigController != value) + { + if ((object)_cameraRigController != null) + { + OnCameraRigControllerLost(_cameraRigController); + } + _cameraRigController = value; + if ((object)_cameraRigController != null) + { + OnCameraRigControllerDiscovered(_cameraRigController); + } + } + } + } + + public GameObject target + { + get + { + return _target; + } + private set + { + if ((object)_target != value) + { + if ((object)_target != null) + { + OnTargetLost(_target); + } + _target = value; + if ((object)_target != null) + { + OnTargetDiscovered(_target); + } + } + } + } + + public event Action onTargetDiscovered; + + public event Action onTargetLost; + + private void OnEnable() + { + InstanceTracker.Add(this); + } + + private void OnDisable() + { + InstanceTracker.Remove(this); + } + + private void OnDestroy() + { + target = null; + cameraRigController = null; + List list = CollectionPool>.RentCollection(); + SetOverlays(list); + CollectionPool>.ReturnCollection(list); + } + + private void Update() + { + cameraRigController = (hud ? hud.cameraRigController : null); + target = (cameraRigController ? cameraRigController.target : null); + List list = CollectionPool>.RentCollection(); + HudOverlayManager.GetGlobalOverlayControllers(list); + HudOverlayManager.GetTargetTracker(target)?.GetOverlayControllers(list); + SetOverlays(list); + CollectionPool>.ReturnCollection(list); + } + + private void OnCameraRigControllerDiscovered(CameraRigController cameraRigController) + { + target = cameraRigController.target; + } + + private void OnCameraRigControllerLost(CameraRigController cameraRigController) + { + target = null; + } + + private void OnTargetDiscovered(GameObject target) + { + } + + private void OnTargetLost(GameObject target) + { + } + + private void AddOverlay(OverlayController overlayController) + { + Transform transform = childLocator.FindChild(overlayController.creationParams.childLocatorEntry); + if ((bool)transform) + { + GameObject gameObject = UnityEngine.Object.Instantiate(overlayController.creationParams.prefab, transform); + overlayControllerToInstance[overlayController] = gameObject; + overlayController.OnInstanceAdded(gameObject); + } + } + + private void RemoveOverlay(OverlayController overlayController) + { + if (overlayControllerToInstance.TryGetValue(overlayController, out var value)) + { + overlayControllerToInstance.Remove(overlayController); + overlayController.OnInstanceRemoved(value); + UnityEngine.Object.Destroy(value); + } + } + + private void SetOverlays(List newOverlayControllers) + { + List list = CollectionPool>.RentCollection(); + List list2 = CollectionPool>.RentCollection(); + for (int num = overlayControllerToInstance.Count - 1; num >= 0; num--) + { + OverlayController key = overlayControllerToInstance[num].Key; + if (!newOverlayControllers.Contains(key)) + { + list2.Add(key); + } + } + for (int i = 0; i < newOverlayControllers.Count; i++) + { + OverlayController overlayController = newOverlayControllers[i]; + if (!overlayControllerToInstance.ContainsKey(overlayController)) + { + list.Add(overlayController); + } + } + foreach (OverlayController item in list2) + { + RemoveOverlay(item); + } + foreach (OverlayController item2 in list) + { + AddOverlay(item2); + } + CollectionPool>.ReturnCollection(list2); + CollectionPool>.ReturnCollection(list); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.HudOverlay/OverlayController.cs b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/OverlayController.cs new file mode 100644 index 0000000..5085774 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/OverlayController.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace RoR2.HudOverlay; + +public class OverlayController +{ + public readonly TargetTracker owner; + + public readonly OverlayCreationParams creationParams; + + private readonly List _instancesList = new List(); + + private bool _active = true; + + private float _alpha = 1f; + + public IReadOnlyList instancesList => _instancesList; + + public bool active + { + get + { + return _active; + } + set + { + if (_active == value) + { + return; + } + _active = value; + foreach (GameObject instances in _instancesList) + { + instances.SetActive(_active); + } + } + } + + public float alpha + { + get + { + return _alpha; + } + set + { + if (_alpha.Equals(value)) + { + return; + } + _alpha = value; + foreach (GameObject instances in _instancesList) + { + PushAlphaToInstance(instances); + } + } + } + + public event Action onInstanceAdded; + + public event Action onInstanceRemove; + + public OverlayController(TargetTracker owner, OverlayCreationParams creationParams) + { + this.owner = owner; + this.creationParams = creationParams; + } + + public void OnInstanceAdded(GameObject instance) + { + _instancesList.Add(instance); + try + { + this.onInstanceAdded?.Invoke(this, instance); + } + catch (Exception message) + { + Debug.LogError(message); + } + instance.SetActive(active); + PushAlphaToInstance(instance); + } + + public void OnInstanceRemoved(GameObject instance) + { + try + { + this.onInstanceRemove?.Invoke(this, instance); + } + catch (Exception message) + { + Debug.LogError(message); + } + _instancesList.Remove(instance); + } + + private void PushAlphaToInstance(GameObject instance) + { + CanvasGroup component = instance.GetComponent(); + if ((bool)component) + { + component.alpha = alpha; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.HudOverlay/OverlayCreationParams.cs b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/OverlayCreationParams.cs new file mode 100644 index 0000000..09c3682 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/OverlayCreationParams.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace RoR2.HudOverlay; + +public struct OverlayCreationParams +{ + public GameObject prefab; + + public string childLocatorEntry; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.HudOverlay/TargetTracker.cs b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/TargetTracker.cs new file mode 100644 index 0000000..8eb7641 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.HudOverlay/TargetTracker.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using HG; +using UnityEngine; + +namespace RoR2.HudOverlay; + +public class TargetTracker : IDisposable +{ + public GameObject target; + + public int refCount; + + private List overlayControllers; + + private bool disposed; + + public TargetTracker() + { + overlayControllers = CollectionPool>.RentCollection(); + } + + public void Dispose() + { + if (!disposed) + { + disposed = true; + while (overlayControllers.Count > 0) + { + RemoveOverlayAt(overlayControllers.Count - 1); + } + overlayControllers = CollectionPool>.ReturnCollection(overlayControllers); + } + } + + public void AddOverlay(OverlayController overlayController) + { + overlayControllers.Add(overlayController); + } + + public void RemoveOverlay(OverlayController overlayController) + { + int i = overlayControllers.IndexOf(overlayController); + RemoveOverlayAt(i); + } + + private void RemoveOverlayAt(int i) + { + overlayControllers.RemoveAt(i); + } + + public void GetOverlayControllers(List dest) + { + ListUtils.AddRange(dest, overlayControllers); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/BaseItemBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/BaseItemBodyBehavior.cs new file mode 100644 index 0000000..37e40d8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/BaseItemBodyBehavior.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using HG; +using HG.Reflection; +using JetBrains.Annotations; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Items; + +public abstract class BaseItemBodyBehavior : MonoBehaviour +{ + private struct ItemTypePair + { + public ItemIndex itemIndex; + + public Type behaviorType; + } + + private struct NetworkContextSet + { + public ItemTypePair[] itemTypePairs; + + public FixedSizeArrayPool behaviorArraysPool; + + public void SetItemTypePairs(List itemTypePairs) + { + this.itemTypePairs = itemTypePairs.ToArray(); + behaviorArraysPool = new FixedSizeArrayPool(this.itemTypePairs.Length); + } + } + + [MeansImplicitUse] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public class ItemDefAssociationAttribute : HG.Reflection.SearchableAttribute + { + public Type behaviorTypeOverride; + + public bool useOnServer = true; + + public bool useOnClient = true; + } + + public int stack; + + private static NetworkContextSet server; + + private static NetworkContextSet client; + + private static NetworkContextSet shared; + + private static CharacterBody earlyAssignmentBody = null; + + private static Dictionary, BaseItemBodyBehavior[]> bodyToItemBehaviors = new Dictionary, BaseItemBodyBehavior[]>(); + + public CharacterBody body { get; private set; } + + protected void Awake() + { + body = earlyAssignmentBody; + earlyAssignmentBody = null; + } + + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + List list = new List(); + List list2 = new List(); + List list3 = new List(); + List list4 = new List(); + HG.Reflection.SearchableAttribute.GetInstances(list4); + Type typeFromHandle = typeof(BaseItemBodyBehavior); + Type typeFromHandle2 = typeof(ItemDef); + foreach (ItemDefAssociationAttribute item in list4) + { + if (!(item.target is MethodInfo methodInfo)) + { + Debug.LogError("ItemDefAssociationAttribute cannot be applied to object of type '" + item?.GetType().FullName + "'"); + continue; + } + if (!methodInfo.IsStatic) + { + Debug.LogError("ItemDefAssociationAttribute cannot be applied to method " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + ": Method is not static."); + continue; + } + Type type = item.behaviorTypeOverride ?? methodInfo.DeclaringType; + if (!typeFromHandle.IsAssignableFrom(type)) + { + Debug.LogError("ItemDefAssociationAttribute cannot be applied to method " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + ": " + methodInfo.DeclaringType.FullName + " does not derive from " + typeFromHandle.FullName + "."); + continue; + } + if (type.IsAbstract) + { + Debug.LogError("ItemDefAssociationAttribute cannot be applied to method " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + ": " + methodInfo.DeclaringType.FullName + " is an abstract type."); + continue; + } + if (!typeFromHandle2.IsAssignableFrom(methodInfo.ReturnType)) + { + Debug.LogError(string.Format("{0} cannot be applied to method {1}.{2}: {3}.{4} returns type '{5}' instead of {6}.", "ItemDefAssociationAttribute", methodInfo.DeclaringType.FullName, methodInfo.Name, methodInfo.DeclaringType.FullName, methodInfo, methodInfo.ReturnType?.FullName ?? "void", typeFromHandle2.FullName)); + continue; + } + if (methodInfo.GetGenericArguments().Length != 0) + { + Debug.LogError(string.Format("{0} cannot be applied to method {1}.{2}: {3}.{4} must take no arguments.", "ItemDefAssociationAttribute", methodInfo.DeclaringType.FullName, methodInfo.Name, methodInfo.DeclaringType.FullName, methodInfo)); + continue; + } + ItemDef itemDef = (ItemDef)methodInfo.Invoke(null, Array.Empty()); + if (!itemDef) + { + Debug.LogError(methodInfo.DeclaringType.FullName + "." + methodInfo.Name + " returned null."); + continue; + } + if (itemDef.itemIndex < ItemIndex.Count) + { + Debug.LogError($"{methodInfo.DeclaringType.FullName}.{methodInfo.Name} returned an ItemDef that's not registered in the ItemCatalog. result={itemDef}"); + continue; + } + if (item.useOnServer) + { + list.Add(new ItemTypePair + { + itemIndex = itemDef.itemIndex, + behaviorType = type + }); + } + if (item.useOnClient) + { + list2.Add(new ItemTypePair + { + itemIndex = itemDef.itemIndex, + behaviorType = type + }); + } + if (item.useOnServer || item.useOnClient) + { + list3.Add(new ItemTypePair + { + itemIndex = itemDef.itemIndex, + behaviorType = type + }); + } + } + server.SetItemTypePairs(list); + client.SetItemTypePairs(list2); + shared.SetItemTypePairs(list3); + CharacterBody.onBodyAwakeGlobal += OnBodyAwakeGlobal; + CharacterBody.onBodyDestroyGlobal += OnBodyDestroyGlobal; + CharacterBody.onBodyInventoryChangedGlobal += OnBodyInventoryChangedGlobal; + } + + private static ref NetworkContextSet GetNetworkContext() + { + bool active = NetworkServer.active; + bool active2 = NetworkClient.active; + if (active) + { + if (active2) + { + return ref shared; + } + return ref server; + } + if (active2) + { + return ref client; + } + throw new InvalidOperationException("Neither server nor client is running."); + } + + private static void OnBodyAwakeGlobal(CharacterBody body) + { + BaseItemBodyBehavior[] value = GetNetworkContext().behaviorArraysPool.Request(); + bodyToItemBehaviors.Add(body, value); + } + + private static void OnBodyDestroyGlobal(CharacterBody body) + { + BaseItemBodyBehavior[] array = bodyToItemBehaviors[body]; + for (int i = 0; i < array.Length; i++) + { + UnityEngine.Object.Destroy(array[i]); + } + bodyToItemBehaviors.Remove(body); + if (NetworkServer.active || NetworkClient.active) + { + GetNetworkContext().behaviorArraysPool.Return(array); + } + } + + private static void OnBodyInventoryChangedGlobal(CharacterBody body) + { + UpdateBodyItemBehaviorStacks(body); + } + + private static void UpdateBodyItemBehaviorStacks(CharacterBody body) + { + ref NetworkContextSet networkContext = ref GetNetworkContext(); + BaseItemBodyBehavior[] array = bodyToItemBehaviors[body]; + ItemTypePair[] itemTypePairs = networkContext.itemTypePairs; + Inventory inventory = body.inventory; + if ((bool)inventory) + { + for (int i = 0; i < itemTypePairs.Length; i++) + { + ItemTypePair itemTypePair = itemTypePairs[i]; + SetItemStack(body, ref array[i], itemTypePair.behaviorType, inventory.GetItemCount(itemTypePair.itemIndex)); + } + return; + } + for (int j = 0; j < itemTypePairs.Length; j++) + { + ref BaseItemBodyBehavior reference = ref array[j]; + if ((object)reference != null) + { + UnityEngine.Object.Destroy(reference); + reference = null; + } + } + } + + private static void SetItemStack(CharacterBody body, ref BaseItemBodyBehavior behavior, Type behaviorType, int stack) + { + if ((object)behavior == null != stack <= 0) + { + if (stack <= 0) + { + UnityEngine.Object.Destroy(behavior); + behavior = null; + } + else + { + earlyAssignmentBody = body; + behavior = (BaseItemBodyBehavior)body.gameObject.AddComponent(behaviorType); + earlyAssignmentBody = null; + } + } + if ((object)behavior != null) + { + behavior.stack = stack; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/BeetleGlandBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/BeetleGlandBodyBehavior.cs new file mode 100644 index 0000000..0947d7f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/BeetleGlandBodyBehavior.cs @@ -0,0 +1,73 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class BeetleGlandBodyBehavior : BaseItemBodyBehavior +{ + private static readonly float timeBetweenGuardResummons = 30f; + + private static readonly float timeBetweenGuardRetryResummons = 1f; + + private float guardResummonCooldown; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.BeetleGland; + } + + private void FixedUpdate() + { + int num = stack; + CharacterMaster bodyMaster = base.body.master; + if (!bodyMaster) + { + return; + } + int deployableCount = bodyMaster.GetDeployableCount(DeployableSlot.BeetleGuardAlly); + if (deployableCount >= num) + { + return; + } + guardResummonCooldown -= Time.fixedDeltaTime; + if (guardResummonCooldown <= 0f) + { + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscBeetleGuardAlly"), new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Approximate, + minDistance = 3f, + maxDistance = 40f, + spawnOnTarget = base.transform + }, RoR2Application.rng); + directorSpawnRequest.summonerBodyObject = base.gameObject; + directorSpawnRequest.onSpawnedServer = OnGuardMasterSpawned; + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + if (deployableCount < num) + { + guardResummonCooldown = timeBetweenGuardRetryResummons; + } + else + { + guardResummonCooldown = timeBetweenGuardResummons; + } + } + void OnGuardMasterSpawned(SpawnCard.SpawnResult spawnResult) + { + GameObject spawnedInstance = spawnResult.spawnedInstance; + if ((bool)spawnedInstance) + { + CharacterMaster component = spawnedInstance.GetComponent(); + if ((bool)component) + { + component.inventory.GiveItem(RoR2Content.Items.BoostDamage, 30); + component.inventory.GiveItem(RoR2Content.Items.BoostHp, 10); + Deployable component2 = component.GetComponent(); + if ((bool)component2) + { + bodyMaster.AddDeployable(component2, DeployableSlot.BeetleGuardAlly); + } + } + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/CaptainDefenseMatrixBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/CaptainDefenseMatrixBodyBehavior.cs new file mode 100644 index 0000000..6fb0004 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/CaptainDefenseMatrixBodyBehavior.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class CaptainDefenseMatrixBodyBehavior : BaseItemBodyBehavior +{ + private GameObject attachmentGameObject; + + private NetworkedBodyAttachment attachment; + + private bool attachmentActive + { + get + { + return (object)attachment != null; + } + set + { + if (value != attachmentActive) + { + if (value) + { + attachmentGameObject = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/BodyAttachments/CaptainDefenseMatrixItemBodyAttachment")); + attachment = attachmentGameObject.GetComponent(); + attachment.AttachToGameObjectAndSpawn(base.body.gameObject); + } + else + { + Object.Destroy(attachmentGameObject); + attachmentGameObject = null; + attachment = null; + } + } + } + } + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.CaptainDefenseMatrix; + } + + private void OnDisable() + { + attachmentActive = false; + } + + private void FixedUpdate() + { + attachmentActive = base.body.healthComponent.alive; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/ContagiousItemManager.cs b/ilspy_dump/ror2_csproj/RoR2.Items/ContagiousItemManager.cs new file mode 100644 index 0000000..c4b9a5d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/ContagiousItemManager.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using HG; +using UnityEngine.Networking; + +namespace RoR2.Items; + +public static class ContagiousItemManager +{ + public struct TransformationInfo + { + public ItemIndex originalItem; + + public ItemIndex transformedItem; + } + + private struct InventoryReplacementCandidate + { + public Inventory inventory; + + public ItemIndex originalItem; + + public Run.FixedTimeStamp time; + + public bool isForced; + } + + public static readonly float transformDelay = 0.5f; + + private static ItemIndex[] originalToTransformed = Array.Empty(); + + private static bool[] itemsToCheck = Array.Empty(); + + private static TransformationInfo[] _transformationInfos = Array.Empty(); + + public static ReadOnlyArray transformationInfos = new ReadOnlyArray(_transformationInfos); + + private static List pendingChanges = new List(); + + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + InitTransformationTable(); + Inventory.onInventoryChangedGlobal += OnInventoryChangedGlobal; + RoR2Application.onFixedUpdate += StaticFixedUpdate; + } + + private static void StaticFixedUpdate() + { + if (pendingChanges.Count > 0) + { + ProcessPendingChanges(); + } + } + + private static void InitTransformationTable() + { + originalToTransformed = new ItemIndex[ItemCatalog.itemCount]; + ItemIndex[] array = originalToTransformed; + ItemIndex value = ItemIndex.None; + ArrayUtils.SetAll(array, in value); + itemsToCheck = new bool[ItemCatalog.itemCount]; + foreach (ItemDef.Pair item in ItemCatalog.GetItemPairsForRelationship(DLC1Content.ItemRelationshipTypes.ContagiousItem)) + { + originalToTransformed[(int)item.itemDef1.itemIndex] = item.itemDef2.itemIndex; + itemsToCheck[(int)item.itemDef1.itemIndex] = true; + itemsToCheck[(int)item.itemDef2.itemIndex] = true; + TransformationInfo value2 = new TransformationInfo + { + originalItem = item.itemDef1.itemIndex, + transformedItem = item.itemDef2.itemIndex + }; + ArrayUtils.ArrayAppend(ref _transformationInfos, in value2); + } + transformationInfos = new ReadOnlyArray(_transformationInfos); + } + + public static ItemIndex GetTransformedItemIndex(ItemIndex itemIndex) + { + if (itemIndex >= ItemIndex.Count && (int)itemIndex < originalToTransformed.Length) + { + return originalToTransformed[(int)itemIndex]; + } + return ItemIndex.None; + } + + public static ItemIndex GetOriginalItemIndex(ItemIndex transformedItemIndex) + { + TransformationInfo[] array = _transformationInfos; + for (int i = 0; i < array.Length; i++) + { + TransformationInfo transformationInfo = array[i]; + if (transformedItemIndex == transformationInfo.transformedItem) + { + return transformationInfo.originalItem; + } + } + return ItemIndex.None; + } + + private static int FindInventoryReplacementCandidateIndex(Inventory inventory, ItemIndex originalItem) + { + for (int i = 0; i < pendingChanges.Count; i++) + { + InventoryReplacementCandidate inventoryReplacementCandidate = pendingChanges[i]; + if ((object)inventoryReplacementCandidate.inventory == inventory && inventoryReplacementCandidate.originalItem == originalItem) + { + return i; + } + } + return -1; + } + + private static void ProcessPendingChanges() + { + if (!NetworkServer.active || !Run.instance) + { + pendingChanges.Clear(); + return; + } + for (int num = pendingChanges.Count - 1; num >= 0; num--) + { + InventoryReplacementCandidate value = pendingChanges[num]; + if (value.time.hasPassed) + { + if (!StepInventoryInfection(value.inventory, value.originalItem, int.MaxValue, value.isForced)) + { + pendingChanges.RemoveAt(num); + } + else + { + value.time = Run.FixedTimeStamp.now + transformDelay; + pendingChanges[num] = value; + } + } + } + } + + private static void OnInventoryChangedGlobal(Inventory inventory) + { + if (!NetworkServer.active) + { + return; + } + for (int i = 0; i < _transformationInfos.Length; i++) + { + ref TransformationInfo reference = ref _transformationInfos[i]; + if (inventory.GetItemCount(reference.transformedItem) > 0) + { + TryQueueReplacement(inventory, reference.originalItem, reference.transformedItem, isForced: false); + } + } + } + + private static void TryQueueReplacement(Inventory inventory, ItemIndex originalItemIndex, ItemIndex transformedItemIndex, bool isForced) + { + if (inventory.GetItemCount(originalItemIndex) > 0 && FindInventoryReplacementCandidateIndex(inventory, transformedItemIndex) == -1) + { + pendingChanges.Add(new InventoryReplacementCandidate + { + inventory = inventory, + originalItem = originalItemIndex, + time = Run.FixedTimeStamp.now + transformDelay, + isForced = isForced + }); + } + } + + public static void TryForceReplacement(Inventory inventory, ItemIndex originalItemIndex) + { + ItemIndex transformedItemIndex = GetTransformedItemIndex(originalItemIndex); + if (transformedItemIndex != ItemIndex.None && Run.instance.IsItemAvailable(transformedItemIndex)) + { + TryQueueReplacement(inventory, originalItemIndex, transformedItemIndex, isForced: true); + } + } + + private static bool StepInventoryInfection(Inventory inventory, ItemIndex originalItem, int limit, bool isForced) + { + ItemIndex itemIndex = originalToTransformed[(int)originalItem]; + int itemCount = inventory.GetItemCount(itemIndex); + if (isForced || itemCount > 0) + { + int itemCount2 = inventory.GetItemCount(originalItem); + int num = Math.Min(limit, itemCount2); + if (num > 0) + { + inventory.RemoveItem(originalItem, num); + inventory.GiveItem(itemIndex, num); + CharacterMaster component = inventory.GetComponent(); + if ((bool)component) + { + CharacterMasterNotificationQueue.SendTransformNotification(component, originalItem, itemIndex, CharacterMasterNotificationQueue.TransformationType.ContagiousVoid); + } + return true; + } + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/CrippleWardOnLevelManager.cs b/ilspy_dump/ror2_csproj/RoR2.Items/CrippleWardOnLevelManager.cs new file mode 100644 index 0000000..417235c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/CrippleWardOnLevelManager.cs @@ -0,0 +1,42 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Items; + +public static class CrippleWardOnLevelManager +{ + private static GameObject wardPrefab; + + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + Run.onRunAmbientLevelUp += onRunAmbientLevelUp; + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/CrippleWard", delegate(GameObject operationResult) + { + wardPrefab = operationResult; + }); + } + + private static void onRunAmbientLevelUp(Run run) + { + if (!NetworkServer.active) + { + return; + } + foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList) + { + int itemCount = readOnlyInstances.inventory.GetItemCount(RoR2Content.Items.CrippleWardOnLevel); + if (itemCount > 0) + { + CharacterBody body = readOnlyInstances.GetBody(); + if ((bool)body) + { + GameObject gameObject = UnityEngine.Object.Instantiate(wardPrefab, body.transform.position, Quaternion.identity); + gameObject.GetComponent().Networkradius = 8f + 8f * (float)itemCount; + NetworkServer.Spawn(gameObject); + } + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/ExtraLifeVoidManager.cs b/ilspy_dump/ror2_csproj/RoR2.Items/ExtraLifeVoidManager.cs new file mode 100644 index 0000000..ba5c3e6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/ExtraLifeVoidManager.cs @@ -0,0 +1,36 @@ +using System; +using UnityEngine; + +namespace RoR2.Items; + +public static class ExtraLifeVoidManager +{ + private const ulong seedSalt = 733uL; + + private static Xoroshiro128Plus rng; + + private static string[] voidBodyNames; + + public static GameObject rezEffectPrefab { get; private set; } + + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/Effects/VoidRezEffect", delegate(GameObject operationResult) + { + rezEffectPrefab = operationResult; + }); + voidBodyNames = new string[1] { "NullifierBody" }; + Run.onRunStartGlobal += OnRunStart; + } + + private static void OnRunStart(Run run) + { + rng = new Xoroshiro128Plus(run.seed ^ 0x2DD); + } + + public static GameObject GetNextBodyPrefab() + { + return BodyCatalog.FindBodyPrefab(voidBodyNames[rng.RangeInt(0, voidBodyNames.Length)]); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/HeadstomperBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/HeadstomperBodyBehavior.cs new file mode 100644 index 0000000..be8acc2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/HeadstomperBodyBehavior.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class HeadstomperBodyBehavior : BaseItemBodyBehavior +{ + private GameObject headstompersControllerObject; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.FallBoots; + } + + private void OnEnable() + { + headstompersControllerObject = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/HeadstompersController")); + headstompersControllerObject.GetComponent().AttachToGameObjectAndSpawn(base.body.gameObject); + } + + private void OnDisable() + { + if ((bool)headstompersControllerObject) + { + Object.Destroy(headstompersControllerObject); + headstompersControllerObject = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/IcicleBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/IcicleBodyBehavior.cs new file mode 100644 index 0000000..ae2dad6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/IcicleBodyBehavior.cs @@ -0,0 +1,55 @@ +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.ResourceManagement.AsyncOperations; + +namespace RoR2.Items; + +public class IcicleBodyBehavior : BaseItemBodyBehavior +{ + private static GameObject icicleAuraPrefab; + + private IcicleAuraController icicleAura; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.Icicle; + } + + [InitDuringStartup] + private static void Init() + { + AsyncOperationHandle asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/NetworkedObjects/IcicleAura"); + asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) + { + icicleAuraPrefab = x.Result; + }; + } + + private void OnEnable() + { + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal; + GameObject gameObject = Object.Instantiate(icicleAuraPrefab, base.transform.position, Quaternion.identity); + icicleAura = gameObject.GetComponent(); + icicleAura.Networkowner = base.gameObject; + NetworkServer.Spawn(gameObject); + } + + private void OnDisable() + { + GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal; + if ((bool)icicleAura) + { + Object.Destroy(icicleAura); + icicleAura = null; + } + } + + private void OnCharacterDeathGlobal(DamageReport damageReport) + { + if ((object)damageReport.attackerBody == base.body && (bool)icicleAura) + { + icicleAura.OnOwnerKillOther(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/ImmuneToDebuffBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/ImmuneToDebuffBehavior.cs new file mode 100644 index 0000000..9ba6c0c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/ImmuneToDebuffBehavior.cs @@ -0,0 +1,114 @@ +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace RoR2.Items; + +public class ImmuneToDebuffBehavior : BaseItemBodyBehavior +{ + public const float barrierFraction = 0.1f; + + public const float cooldownSeconds = 5f; + + private HealthComponent healthComponent; + + private bool isProtected; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return DLC1Content.Items.ImmuneToDebuff; + } + + public static bool OverrideDebuff(BuffIndex buffIndex, CharacterBody body) + { + BuffDef buffDef = BuffCatalog.GetBuffDef(buffIndex); + if ((bool)buffDef) + { + return OverrideDebuff(buffDef, body); + } + return false; + } + + public static bool OverrideDebuff(BuffDef buffDef, CharacterBody body) + { + if (buffDef.buffIndex != BuffIndex.None && buffDef.isDebuff) + { + return TryApplyOverride(body); + } + return false; + } + + public static bool OverrideDot(InflictDotInfo inflictDotInfo) + { + CharacterBody characterBody = inflictDotInfo.victimObject?.GetComponent(); + if ((bool)characterBody) + { + return TryApplyOverride(characterBody); + } + return false; + } + + private static bool TryApplyOverride(CharacterBody body) + { + ImmuneToDebuffBehavior component = body.GetComponent(); + if ((bool)component) + { + if (component.isProtected) + { + return true; + } + if (body.HasBuff(DLC1Content.Buffs.ImmuneToDebuffReady) && (bool)component.healthComponent) + { + component.healthComponent.AddBarrier(0.1f * component.healthComponent.fullCombinedHealth); + body.RemoveBuff(DLC1Content.Buffs.ImmuneToDebuffReady); + EffectManager.SimpleImpactEffect(Addressables.LoadAssetAsync("RoR2/DLC1/ImmuneToDebuff/ImmuneToDebuffEffect.prefab").WaitForCompletion(), body.corePosition, Vector3.up, transmit: true); + if (!body.HasBuff(DLC1Content.Buffs.ImmuneToDebuffReady)) + { + body.AddTimedBuff(DLC1Content.Buffs.ImmuneToDebuffCooldown, 5f); + } + component.isProtected = true; + return true; + } + } + return false; + } + + private void OnEnable() + { + healthComponent = GetComponent(); + } + + private void OnDisable() + { + healthComponent = null; + if ((bool)base.body) + { + while (base.body.GetBuffCount(DLC1Content.Buffs.ImmuneToDebuffReady) > 0) + { + base.body.RemoveBuff(DLC1Content.Buffs.ImmuneToDebuffReady); + } + if (base.body.HasBuff(DLC1Content.Buffs.ImmuneToDebuffCooldown)) + { + base.body.RemoveBuff(DLC1Content.Buffs.ImmuneToDebuffCooldown); + } + } + } + + private void FixedUpdate() + { + isProtected = false; + bool flag = base.body.HasBuff(DLC1Content.Buffs.ImmuneToDebuffCooldown); + bool flag2 = base.body.HasBuff(DLC1Content.Buffs.ImmuneToDebuffReady); + if (!flag && !flag2) + { + for (int i = 0; i < stack; i++) + { + base.body.AddBuff(DLC1Content.Buffs.ImmuneToDebuffReady); + } + } + if (flag2 && flag) + { + base.body.RemoveBuff(DLC1Content.Buffs.ImmuneToDebuffReady); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/LaserTurbineBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/LaserTurbineBodyBehavior.cs new file mode 100644 index 0000000..78d78e1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/LaserTurbineBodyBehavior.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class LaserTurbineBodyBehavior : BaseItemBodyBehavior +{ + private GameObject laserTurbineControllerInstance; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.LaserTurbine; + } + + private void OnEnable() + { + laserTurbineControllerInstance = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/LaserTurbineController"), base.body.corePosition, Quaternion.identity); + laserTurbineControllerInstance.GetComponent().ownerObject = base.gameObject; + laserTurbineControllerInstance.GetComponent().AttachToGameObjectAndSpawn(base.gameObject); + } + + private void OnDestroy() + { + Object.Destroy(laserTurbineControllerInstance); + laserTurbineControllerInstance = null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/MinionLeashBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/MinionLeashBodyBehavior.cs new file mode 100644 index 0000000..bf9be00 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/MinionLeashBodyBehavior.cs @@ -0,0 +1,159 @@ +using System.Collections; +using System.Collections.Generic; +using RoR2.Navigation; +using UnityEngine; + +namespace RoR2.Items; + +public class MinionLeashBodyBehavior : BaseItemBodyBehavior +{ + public const float leashDistSq = 160000f; + + public const float teleportDelayTime = 10f; + + public const float minTeleportDistance = 10f; + + public const float maxTeleportDistance = 40f; + + private GameObject helperPrefab; + + private RigidbodyMotor rigidbodyMotor; + + private float teleportAttemptTimer = 10f; + + private float currentTeleportDelayTimer; + + [ItemDefAssociation(useOnServer = true, useOnClient = true)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.MinionLeash; + } + + private void OnEnable() + { + if (SceneInfo.instance.sceneDef.cachedName == "meridian") + { + MeridianEventTriggerInteraction.MeridianEventStart.OnMeridianEventStart += StartTeleporting; + } + } + + private void OnDisable() + { + if (SceneInfo.instance.sceneDef.cachedName == "meridian") + { + MeridianEventTriggerInteraction.MeridianEventStart.OnMeridianEventStart -= StartTeleporting; + } + } + + public void Start() + { + if (base.body.hasEffectiveAuthority) + { + helperPrefab = LegacyResourcesAPI.Load("SpawnCards/HelperPrefab"); + rigidbodyMotor = GetComponent(); + } + } + + private void FixedUpdate() + { + if (!base.body.hasEffectiveAuthority) + { + return; + } + CharacterMaster master = base.body.master; + CharacterMaster characterMaster = (master ? master.minionOwnership.ownerMaster : null); + CharacterBody characterBody = (characterMaster ? characterMaster.GetBody() : null); + if (!characterBody) + { + return; + } + Vector3 corePosition = characterBody.corePosition; + Vector3 corePosition2 = base.body.corePosition; + if (((!base.body.characterMotor || !(base.body.characterMotor.walkSpeed > 0f)) && (!rigidbodyMotor || !(base.body.moveSpeed > 0f))) || !((corePosition2 - corePosition).sqrMagnitude > 160000f)) + { + return; + } + teleportAttemptTimer -= Time.fixedDeltaTime; + if (!(teleportAttemptTimer <= 0f)) + { + return; + } + teleportAttemptTimer = 10f; + SpawnCard spawnCard = ScriptableObject.CreateInstance(); + spawnCard.hullSize = base.body.hullClassification; + spawnCard.nodeGraphType = (base.body.isFlying ? MapNodeGroup.GraphType.Air : MapNodeGroup.GraphType.Ground); + spawnCard.prefab = helperPrefab; + GameObject gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(spawnCard, new DirectorPlacementRule + { + placementMode = DirectorPlacementRule.PlacementMode.Approximate, + position = corePosition, + minDistance = 10f, + maxDistance = 40f + }, RoR2Application.rng)); + if ((bool)gameObject) + { + Vector3 position = gameObject.transform.position; + if ((position - corePosition).sqrMagnitude < 160000f) + { + TeleportHelper.TeleportBody(base.body, position); + GameObject teleportEffectPrefab = Run.instance.GetTeleportEffectPrefab(base.body.gameObject); + if ((bool)teleportEffectPrefab) + { + EffectManager.SimpleEffect(teleportEffectPrefab, position, Quaternion.identity, transmit: true); + } + Object.Destroy(gameObject); + } + } + Object.Destroy(spawnCard); + } + + private void StartTeleporting() + { + CharacterMaster master = base.body.master; + CharacterMaster characterMaster = (master ? master.minionOwnership.ownerMaster : null); + CharacterBody characterBody = (characterMaster ? characterMaster.GetBody() : null); + if (base.body.hasEffectiveAuthority && (bool)characterBody && (((bool)base.body.characterMotor && base.body.characterMotor.walkSpeed > 0f) || ((bool)rigidbodyMotor && base.body.moveSpeed > 0f))) + { + StartCoroutine(Teleport()); + } + } + + private IEnumerator Teleport() + { + currentTeleportDelayTimer = 0f; + while (currentTeleportDelayTimer < 10f) + { + currentTeleportDelayTimer += Time.deltaTime; + yield return null; + } + CharacterMaster master = base.body.master; + CharacterMaster characterMaster = (master ? master.minionOwnership.ownerMaster : null); + CharacterBody ownerBody = (characterMaster ? characterMaster.GetBody() : null); + NodeGraph nodeGraph = SceneInfo.instance.GetNodeGraph(MapNodeGroup.GraphType.Ground); + if (!ownerBody) + { + yield break; + } + List list = nodeGraph.FindNodesInRangeWithFlagConditions(ownerBody.transform.position, 3f, 20f, HullMask.None, NodeFlags.None, NodeFlags.NoCharacterSpawn, preventOverhead: false); + while (list.Count == 0) + { + yield return new WaitForSeconds(1f); + list = nodeGraph.FindNodesInRangeWithFlagConditions(ownerBody.transform.position, 3f, 20f, HullMask.None, NodeFlags.None, NodeFlags.NoCharacterSpawn, preventOverhead: false); + } + while (list.Count > 0) + { + int index = Random.Range(0, list.Count); + NodeGraph.NodeIndex nodeIndex = list[index]; + if (nodeGraph.GetNodePosition(nodeIndex, out var position)) + { + TeleportHelper.TeleportBody(base.body, position); + GameObject teleportEffectPrefab = Run.instance.GetTeleportEffectPrefab(base.body.gameObject); + if ((bool)teleportEffectPrefab) + { + EffectManager.SimpleEffect(teleportEffectPrefab, position, Quaternion.identity, transmit: true); + } + break; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/MultiShopCardUtils.cs b/ilspy_dump/ror2_csproj/RoR2.Items/MultiShopCardUtils.cs new file mode 100644 index 0000000..7c36d03 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/MultiShopCardUtils.cs @@ -0,0 +1,59 @@ +using RoR2.Orbs; + +namespace RoR2.Items; + +public static class MultiShopCardUtils +{ + private const float refundPercentage = 0.1f; + + public static void OnNonMoneyPurchase(CostTypeDef.PayCostContext context) + { + OnPurchase(context, 0); + } + + public static void OnMoneyPurchase(CostTypeDef.PayCostContext context) + { + OnPurchase(context, context.cost); + } + + private static void OnPurchase(CostTypeDef.PayCostContext context, int moneyCost) + { + CharacterMaster activatorMaster = context.activatorMaster; + if (!activatorMaster || !activatorMaster.hasBody || !activatorMaster.inventory || activatorMaster.inventory.currentEquipmentIndex != DLC1Content.Equipment.MultiShopCard.equipmentIndex) + { + return; + } + CharacterBody body = activatorMaster.GetBody(); + if (body.equipmentSlot.stock <= 0) + { + return; + } + bool flag = false; + if (moneyCost > 0) + { + flag = true; + GoldOrb goldOrb = new GoldOrb(); + goldOrb.origin = context.purchasedObject?.transform?.position ?? body.corePosition; + goldOrb.target = body.mainHurtBox; + goldOrb.goldAmount = (uint)(0.1f * (float)moneyCost); + OrbManager.instance.AddOrb(goldOrb); + } + ShopTerminalBehavior shopTerminalBehavior = context.purchasedObject?.GetComponent(); + if ((bool)shopTerminalBehavior && (bool)shopTerminalBehavior.serverMultiShopController) + { + flag = true; + shopTerminalBehavior.serverMultiShopController.SetCloseOnTerminalPurchase(context.purchasedObject.GetComponent(), doCloseMultiShop: false); + } + if (flag) + { + if (body.hasAuthority) + { + body.equipmentSlot.OnEquipmentExecuted(); + } + else + { + body.equipmentSlot.CallCmdOnEquipmentExecuted(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/MushroomBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/MushroomBodyBehavior.cs new file mode 100644 index 0000000..231d543 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/MushroomBodyBehavior.cs @@ -0,0 +1,81 @@ +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.ResourceManagement.AsyncOperations; + +namespace RoR2.Items; + +public class MushroomBodyBehavior : BaseItemBodyBehavior +{ + private static GameObject mushroomWardPrefab; + + private const float baseHealFractionPerSecond = 0.045f; + + private const float healFractionPerSecondPerStack = 0.0225f; + + private GameObject mushroomWardGameObject; + + private HealingWard mushroomHealingWard; + + private TeamFilter mushroomWardTeamFilter; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.Mushroom; + } + + [InitDuringStartup] + private static void Init() + { + AsyncOperationHandle asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/NetworkedObjects/MushroomWard"); + asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) + { + mushroomWardPrefab = x.Result; + }; + } + + private void FixedUpdate() + { + if (!NetworkServer.active) + { + return; + } + int num = stack; + bool flag = num > 0 && base.body.GetNotMoving(); + float networkradius = base.body.radius + 1.5f + 1.5f * (float)num; + if ((bool)mushroomWardGameObject != flag) + { + if (flag) + { + mushroomWardGameObject = Object.Instantiate(mushroomWardPrefab, base.body.footPosition, Quaternion.identity); + mushroomWardTeamFilter = mushroomWardGameObject.GetComponent(); + mushroomHealingWard = mushroomWardGameObject.GetComponent(); + NetworkServer.Spawn(mushroomWardGameObject); + } + else + { + Object.Destroy(mushroomWardGameObject); + mushroomWardGameObject = null; + } + } + if ((bool)mushroomHealingWard) + { + mushroomHealingWard.interval = 0.25f; + mushroomHealingWard.healFraction = (0.045f + 0.0225f * (float)(num - 1)) * mushroomHealingWard.interval; + mushroomHealingWard.healPoints = 0f; + mushroomHealingWard.Networkradius = networkradius; + } + if ((bool)mushroomWardTeamFilter) + { + mushroomWardTeamFilter.teamIndex = base.body.teamComponent.teamIndex; + } + } + + private void OnDisable() + { + if ((bool)mushroomWardGameObject) + { + Object.Destroy(mushroomWardGameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/NearbyDamageBonusBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/NearbyDamageBonusBodyBehavior.cs new file mode 100644 index 0000000..5a49ca3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/NearbyDamageBonusBodyBehavior.cs @@ -0,0 +1,49 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class NearbyDamageBonusBodyBehavior : BaseItemBodyBehavior +{ + private GameObject nearbyDamageBonusIndicator; + + private bool indicatorEnabled + { + get + { + return nearbyDamageBonusIndicator; + } + set + { + if (indicatorEnabled != value) + { + if (value) + { + GameObject original = LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/NearbyDamageBonusIndicator"); + nearbyDamageBonusIndicator = Object.Instantiate(original, base.body.corePosition, Quaternion.identity); + nearbyDamageBonusIndicator.GetComponent().AttachToGameObjectAndSpawn(base.gameObject); + } + else + { + Object.Destroy(nearbyDamageBonusIndicator); + nearbyDamageBonusIndicator = null; + } + } + } + } + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.NearbyDamageBonus; + } + + private void OnEnable() + { + indicatorEnabled = true; + } + + private void OnDisable() + { + indicatorEnabled = false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/NovaOnLowHealthBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/NovaOnLowHealthBodyBehavior.cs new file mode 100644 index 0000000..bea72d6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/NovaOnLowHealthBodyBehavior.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class NovaOnLowHealthBodyBehavior : BaseItemBodyBehavior +{ + private NetworkedBodyAttachment attachment; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.NovaOnLowHealth; + } + + private void Start() + { + attachment = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/BodyAttachments/VagrantNovaItemBodyAttachment")).GetComponent(); + attachment.AttachToGameObjectAndSpawn(base.body.gameObject); + } + + private void FixedUpdate() + { + if (!base.body.healthComponent.alive) + { + Object.Destroy(this); + } + } + + private void OnDestroy() + { + if ((bool)attachment) + { + Object.Destroy(attachment.gameObject); + attachment = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/PhasingBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/PhasingBodyBehavior.cs new file mode 100644 index 0000000..d96ffbb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/PhasingBodyBehavior.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class PhasingBodyBehavior : BaseItemBodyBehavior +{ + private readonly float baseRechargeSeconds = 30f; + + private readonly float rechargeReductionMultiplierPerStack = 0.5f; + + private readonly float buffDuration = 5f; + + private float rechargeStopwatch; + + private GameObject effectPrefab; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.Phasing; + } + + private void Start() + { + rechargeStopwatch = baseRechargeSeconds; + effectPrefab = LegacyResourcesAPI.Load("Prefabs/Effects/ProcStealthkit"); + } + + private void FixedUpdate() + { + if (base.body.healthComponent.alive) + { + rechargeStopwatch += Time.fixedDeltaTime; + if (base.body.healthComponent.isHealthLow && !base.body.hasCloakBuff && rechargeStopwatch >= buffDuration + baseRechargeSeconds * Mathf.Pow(rechargeReductionMultiplierPerStack, stack - 1)) + { + base.body.AddTimedBuff(RoR2Content.Buffs.Cloak, buffDuration); + base.body.AddTimedBuff(RoR2Content.Buffs.CloakSpeed, buffDuration); + EffectManager.SpawnEffect(effectPrefab, new EffectData + { + origin = base.transform.position, + rotation = Quaternion.identity + }, transmit: true); + rechargeStopwatch = 0f; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/RandomDamageZoneBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/RandomDamageZoneBodyBehavior.cs new file mode 100644 index 0000000..723a71d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/RandomDamageZoneBodyBehavior.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using RoR2.Navigation; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Items; + +public class RandomDamageZoneBodyBehavior : BaseItemBodyBehavior +{ + private static readonly float wardDuration = 25f; + + private static readonly float wardRespawnRetryTime = 1f; + + private static readonly float baseWardRadius = 16f; + + private static readonly float wardRadiusMultiplierPerStack = 1.5f; + + private float wardResummonCooldown; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.RandomDamageZone; + } + + private void FixedUpdate() + { + CharacterMaster master = base.body.master; + if (!master || !master.IsDeployableSlotAvailable(DeployableSlot.PowerWard)) + { + return; + } + wardResummonCooldown -= Time.fixedDeltaTime; + if (!(wardResummonCooldown <= 0f)) + { + return; + } + wardResummonCooldown = wardRespawnRetryTime; + if (master.IsDeployableSlotAvailable(DeployableSlot.PowerWard)) + { + Vector3? vector = FindWardSpawnPosition(base.body.corePosition); + if (vector.HasValue) + { + GameObject gameObject = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/DamageZoneWard"), vector.Value, Quaternion.identity); + Util.PlaySound("Play_randomDamageZone_appear", gameObject.gameObject); + gameObject.GetComponent().teamIndex = TeamIndex.None; + BuffWard component = gameObject.GetComponent(); + component.Networkradius = baseWardRadius * Mathf.Pow(wardRadiusMultiplierPerStack, stack - 1); + component.expireDuration = wardDuration; + NetworkServer.Spawn(gameObject); + Deployable component2 = gameObject.GetComponent(); + master.AddDeployable(component2, DeployableSlot.PowerWard); + } + } + } + + private Vector3? FindWardSpawnPosition(Vector3 ownerPosition) + { + if (!SceneInfo.instance) + { + return null; + } + NodeGraph groundNodes = SceneInfo.instance.groundNodes; + if (!groundNodes) + { + return null; + } + List list = groundNodes.FindNodesInRange(ownerPosition, 0f, 50f, HullMask.None); + if (list.Count > 0 && groundNodes.GetNodePosition(list[(int)Random.Range(0f, list.Count)], out var position)) + { + return position; + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/RandomlyLunarUtils.cs b/ilspy_dump/ror2_csproj/RoR2.Items/RandomlyLunarUtils.cs new file mode 100644 index 0000000..dd7b851 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/RandomlyLunarUtils.cs @@ -0,0 +1,82 @@ +using System.Collections.Generic; + +namespace RoR2.Items; + +public static class RandomlyLunarUtils +{ + private const float replacePercentagePerStack = 0.05f; + + public static PickupIndex CheckForLunarReplacement(PickupIndex pickupIndex, Xoroshiro128Plus rng) + { + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + if (CanReplace(pickupDef)) + { + int itemCountGlobal = Util.GetItemCountGlobal(DLC1Content.Items.RandomlyLunar.itemIndex, requiresAlive: false, requiresConnected: false); + if (itemCountGlobal > 0) + { + List list = null; + if (pickupDef.itemIndex != ItemIndex.None) + { + list = Run.instance.availableLunarItemDropList; + } + else if (pickupDef.equipmentIndex != EquipmentIndex.None) + { + list = Run.instance.availableLunarEquipmentDropList; + } + if (list != null && list.Count > 0 && rng.nextNormalizedFloat < 0.05f * (float)itemCountGlobal) + { + int index = rng.RangeInt(0, list.Count); + return list[index]; + } + } + } + return pickupIndex; + } + + public static void CheckForLunarReplacementUniqueArray(PickupIndex[] pickupIndices, Xoroshiro128Plus rng) + { + int itemCountGlobal = Util.GetItemCountGlobal(DLC1Content.Items.RandomlyLunar.itemIndex, requiresAlive: false, requiresConnected: false); + if (itemCountGlobal <= 0) + { + return; + } + List list = null; + List list2 = null; + for (int i = 0; i < pickupIndices.Length; i++) + { + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndices[i]); + if (!CanReplace(pickupDef) || !(rng.nextNormalizedFloat < 0.05f * (float)itemCountGlobal)) + { + continue; + } + List list3 = null; + if (pickupDef.itemIndex != ItemIndex.None) + { + if (list == null) + { + list = new List(Run.instance.availableLunarItemDropList); + Util.ShuffleList(list, rng); + } + list3 = list; + } + else if (pickupDef.equipmentIndex != EquipmentIndex.None) + { + if (list2 == null) + { + list2 = new List(Run.instance.availableLunarEquipmentDropList); + Util.ShuffleList(list2, rng); + } + list3 = list2; + } + if (list3 != null && list3.Count > 0) + { + pickupIndices[i] = list3[i % list3.Count]; + } + } + } + + public static bool CanReplace(PickupDef pickupDef) + { + return !(pickupDef?.isLunar ?? true); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/RedWhipBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/RedWhipBodyBehavior.cs new file mode 100644 index 0000000..aca38e5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/RedWhipBodyBehavior.cs @@ -0,0 +1,55 @@ +using UnityEngine; + +namespace RoR2.Items; + +internal class RedWhipBodyBehavior : BaseItemBodyBehavior +{ + private bool providingBuff; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.SprintOutOfCombat; + } + + private void SetProvidingBuff(bool shouldProvideBuff) + { + if (shouldProvideBuff == providingBuff) + { + return; + } + providingBuff = shouldProvideBuff; + if (providingBuff) + { + base.body.AddBuff(RoR2Content.Buffs.WhipBoost); + EffectData effectData = new EffectData(); + effectData.origin = base.body.corePosition; + CharacterDirection characterDirection = base.body.characterDirection; + bool flag = false; + if ((bool)characterDirection && characterDirection.moveVector != Vector3.zero) + { + effectData.rotation = Util.QuaternionSafeLookRotation(characterDirection.moveVector); + flag = true; + } + if (!flag) + { + effectData.rotation = base.body.transform.rotation; + } + EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/SprintActivate"), effectData, transmit: true); + } + else + { + base.body.RemoveBuff(RoR2Content.Buffs.WhipBoost); + } + } + + private void OnDisable() + { + SetProvidingBuff(shouldProvideBuff: false); + } + + private void FixedUpdate() + { + SetProvidingBuff(base.body.outOfCombat); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/RoboBallBuddyBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/RoboBallBuddyBodyBehavior.cs new file mode 100644 index 0000000..2a3dd2a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/RoboBallBuddyBodyBehavior.cs @@ -0,0 +1,97 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class RoboBallBuddyBodyBehavior : BaseItemBodyBehavior +{ + private class InventorySync : MonoBehaviour + { + public Inventory srcInventory; + + public Inventory destInventory; + + private int granted; + + private void FixedUpdate() + { + if ((bool)srcInventory && (bool)destInventory) + { + int itemCount = srcInventory.GetItemCount(RoR2Content.Items.RoboBallBuddy); + int num = itemCount - granted; + if (num != 0) + { + destInventory.GiveItem(RoR2Content.Items.TeamSizeDamageBonus, num); + granted = itemCount; + } + } + } + } + + private DeployableMinionSpawner redBuddySpawner; + + private DeployableMinionSpawner greenBuddySpawner; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.RoboBallBuddy; + } + + private void FixedUpdate() + { + if (redBuddySpawner == null && base.isActiveAndEnabled) + { + CreateSpawners(); + } + } + + private void OnDisable() + { + DestroySpawners(); + } + + private void CreateSpawners() + { + Xoroshiro128Plus rng = new Xoroshiro128Plus(Run.instance.seed ^ (ulong)GetInstanceID()); + CreateSpawner(ref redBuddySpawner, DeployableSlot.RoboBallRedBuddy, LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscRoboBallRedBuddy")); + CreateSpawner(ref greenBuddySpawner, DeployableSlot.RoboBallGreenBuddy, LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscRoboBallGreenBuddy")); + void CreateSpawner(ref DeployableMinionSpawner buddySpawner, DeployableSlot deployableSlot, SpawnCard spawnCard) + { + buddySpawner = new DeployableMinionSpawner(base.body.master, deployableSlot, rng) + { + respawnInterval = 30f, + spawnCard = spawnCard + }; + buddySpawner.onMinionSpawnedServer += OnMinionSpawnedServer; + } + } + + private void DestroySpawners() + { + redBuddySpawner?.Dispose(); + redBuddySpawner = null; + greenBuddySpawner?.Dispose(); + greenBuddySpawner = null; + } + + private void OnMinionSpawnedServer(SpawnCard.SpawnResult spawnResult) + { + GameObject spawnedInstance = spawnResult.spawnedInstance; + if (!spawnedInstance) + { + return; + } + CharacterMaster component = spawnedInstance.GetComponent(); + if ((bool)component) + { + Inventory inventory = base.body.inventory; + Inventory inventory2 = component.inventory; + if ((bool)inventory) + { + InventorySync inventorySync = spawnedInstance.AddComponent(); + inventorySync.srcInventory = inventory; + inventorySync.destInventory = inventory2; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/ShockNearbyBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/ShockNearbyBodyBehavior.cs new file mode 100644 index 0000000..d719900 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/ShockNearbyBodyBehavior.cs @@ -0,0 +1,114 @@ +using System.Collections.Generic; +using RoR2.Orbs; +using UnityEngine; + +namespace RoR2.Items; + +public class ShockNearbyBodyBehavior : BaseItemBodyBehavior +{ + private float teslaBuffRollTimer; + + private const float teslaRollInterval = 10f; + + private float teslaFireTimer; + + private float teslaResetListTimer; + + private float teslaResetListInterval = 0.5f; + + private const float teslaFireInterval = 1f / 12f; + + private bool teslaCrit; + + private bool teslaIsOn; + + private List previousTeslaTargetList = new List(); + + private bool _grantingBuff; + + private BuffDef grantedBuff => RoR2Content.Buffs.TeslaField; + + private bool grantingBuff + { + get + { + return _grantingBuff; + } + set + { + if (_grantingBuff != value) + { + _grantingBuff = value; + if (_grantingBuff) + { + base.body.AddBuff(grantedBuff); + } + else + { + base.body.RemoveBuff(grantedBuff); + } + } + } + } + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.ShockNearby; + } + + private void FixedUpdate() + { + teslaBuffRollTimer += Time.fixedDeltaTime; + if (teslaBuffRollTimer >= 10f) + { + teslaBuffRollTimer = 0f; + teslaCrit = base.body.RollCrit(); + grantingBuff = !grantingBuff; + } + if (!grantingBuff) + { + return; + } + teslaFireTimer += Time.fixedDeltaTime; + teslaResetListTimer += Time.fixedDeltaTime; + if (teslaFireTimer >= 1f / 12f) + { + teslaFireTimer = 0f; + LightningOrb lightningOrb = new LightningOrb + { + origin = base.body.corePosition, + damageValue = base.body.damage * 2f, + isCrit = teslaCrit, + bouncesRemaining = 2 * stack, + teamIndex = base.body.teamComponent.teamIndex, + attacker = base.gameObject, + procCoefficient = 0.3f, + bouncedObjects = previousTeslaTargetList, + lightningType = LightningOrb.LightningType.Tesla, + damageColorIndex = DamageColorIndex.Item, + range = 35f + }; + HurtBox hurtBox = lightningOrb.PickNextTarget(base.transform.position); + if ((bool)hurtBox) + { + previousTeslaTargetList.Add(hurtBox.healthComponent); + lightningOrb.target = hurtBox; + OrbManager.instance.AddOrb(lightningOrb); + } + } + if (teslaResetListTimer >= teslaResetListInterval) + { + teslaResetListTimer -= teslaResetListInterval; + previousTeslaTargetList.Clear(); + } + } + + private void OnDisable() + { + if ((bool)base.body && base.body.HasBuff(grantedBuff)) + { + base.body.RemoveBuff(grantedBuff); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/SiphonOnLowHealthItemBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/SiphonOnLowHealthItemBodyBehavior.cs new file mode 100644 index 0000000..ed59bc6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/SiphonOnLowHealthItemBodyBehavior.cs @@ -0,0 +1,43 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class SiphonOnLowHealthItemBodyBehavior : BaseItemBodyBehavior +{ + private NetworkedBodyAttachment attachment; + + private SiphonNearbyController siphonNearbyController; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.SiphonOnLowHealth; + } + + private void OnEnable() + { + attachment = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/BodyAttachments/SiphonNearbyBodyAttachment")).GetComponent(); + attachment.AttachToGameObjectAndSpawn(base.body.gameObject); + siphonNearbyController = attachment.GetComponent(); + } + + private void OnDisable() + { + DestroyAttachment(); + } + + private void FixedUpdate() + { + siphonNearbyController.NetworkmaxTargets = (base.body.healthComponent.alive ? stack : 0); + } + + private void DestroyAttachment() + { + if ((bool)attachment) + { + Object.Destroy(attachment.gameObject); + } + attachment = null; + siphonNearbyController = null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/SprintWispBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/SprintWispBodyBehavior.cs new file mode 100644 index 0000000..6923b8b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/SprintWispBodyBehavior.cs @@ -0,0 +1,54 @@ +using RoR2.Orbs; +using UnityEngine; + +namespace RoR2.Items; + +public class SprintWispBodyBehavior : BaseItemBodyBehavior +{ + private static readonly float fireRate = 3f / 35f; + + private static readonly float searchRadius = 40f; + + private static readonly float damageCoefficient = 3f; + + private float fireTimer; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.SprintWisp; + } + + private void FixedUpdate() + { + if (base.body.isSprinting) + { + fireTimer -= Time.fixedDeltaTime; + if (fireTimer <= 0f && base.body.moveSpeed > 0f) + { + fireTimer += 1f / (fireRate * base.body.moveSpeed); + Fire(); + } + } + } + + private void Fire() + { + DevilOrb devilOrb = new DevilOrb + { + origin = base.body.corePosition, + damageValue = base.body.damage * damageCoefficient * (float)stack, + teamIndex = base.body.teamComponent.teamIndex, + attacker = base.gameObject, + damageColorIndex = DamageColorIndex.Item, + scale = 1f, + effectType = DevilOrb.EffectType.Wisp, + procCoefficient = 1f + }; + if ((bool)(devilOrb.target = devilOrb.PickNextTarget(devilOrb.origin, searchRadius))) + { + devilOrb.isCrit = Util.CheckRoll(base.body.crit, base.body.master); + OrbManager.instance.AddOrb(devilOrb); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/SummonedEchoBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/SummonedEchoBodyBehavior.cs new file mode 100644 index 0000000..54f08db --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/SummonedEchoBodyBehavior.cs @@ -0,0 +1,41 @@ +using RoR2.Projectile; +using UnityEngine; + +namespace RoR2.Items; + +public class SummonedEchoBodyBehavior : BaseItemBodyBehavior +{ + private float fireTimer; + + private float fireInterval = 3f; + + private float damageCoefficient = 3f; + + private static ItemDef GetItemDef() + { + return RoR2Content.Items.SummonedEcho; + } + + private void FixedUpdate() + { + fireTimer -= Time.fixedDeltaTime; + if (fireTimer <= 0f) + { + fireTimer = fireInterval; + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.crit = false; + fireProjectileInfo.damage = base.body.damage * damageCoefficient; + fireProjectileInfo.damageColorIndex = DamageColorIndex.Default; + fireProjectileInfo.damageTypeOverride = DamageType.SlowOnHit; + fireProjectileInfo.owner = base.body.gameObject; + fireProjectileInfo.position = base.body.aimOrigin; + fireProjectileInfo.rotation = Quaternion.LookRotation(Vector3.up); + fireProjectileInfo.procChainMask = default(ProcChainMask); + fireProjectileInfo.projectilePrefab = LegacyResourcesAPI.Load("Prefabs/Projectiles/EchoHunterProjectile"); + fireProjectileInfo.force = 400f; + fireProjectileInfo.target = null; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + ProjectileManager.instance.FireProjectile(fireProjectileInfo2); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/SuppressedItemManager.cs b/ilspy_dump/ror2_csproj/RoR2.Items/SuppressedItemManager.cs new file mode 100644 index 0000000..16d70ac --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/SuppressedItemManager.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Items; + +public static class SuppressedItemManager +{ + private static Dictionary transformationMap = new Dictionary(); + + private static GameObject networkedInventoryPrefab; + + private static HashSet pendingTransformationInventories = new HashSet(); + + public static Inventory suppressedInventory { get; private set; } + + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + Run.onRunStartGlobal += OnRunStart; + Run.onRunDestroyGlobal += OnRunDestroyGlobal; + Inventory.onInventoryChangedGlobal += OnInventoryChangedGlobal; + RoR2Application.onFixedUpdate += StaticFixedUpdate; + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/SuppressedItemInventory", delegate(GameObject operationResult) + { + networkedInventoryPrefab = operationResult; + }); + } + + public static bool HasItemBeenSuppressed(ItemIndex itemIndex) + { + return transformationMap.ContainsKey(itemIndex); + } + + public static bool HasAnyItemBeenSuppressed() + { + return transformationMap.Count > 0; + } + + public static bool SuppressItem(ItemIndex suppressedIndex, ItemIndex transformedIndex = ItemIndex.None) + { + if (!transformationMap.ContainsKey(suppressedIndex)) + { + ItemDef itemDef = ItemCatalog.GetItemDef(suppressedIndex); + if ((bool)itemDef) + { + ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(itemDef.tier); + ItemIndex itemIndex = ItemIndex.None; + bool flag = false; + if ((bool)itemTierDef) + { + switch (itemTierDef.tier) + { + case ItemTier.Tier3: + itemIndex = DLC1Content.Items.ScrapRedSuppressed.itemIndex; + flag = Run.instance.availableTier3DropList.Count == 1; + break; + case ItemTier.Tier2: + itemIndex = DLC1Content.Items.ScrapGreenSuppressed.itemIndex; + flag = Run.instance.availableTier2DropList.Count == 1; + break; + case ItemTier.Tier1: + itemIndex = DLC1Content.Items.ScrapWhiteSuppressed.itemIndex; + flag = Run.instance.availableTier1DropList.Count == 1; + break; + } + } + if (itemIndex != suppressedIndex) + { + PickupIndex pickupIndex = PickupCatalog.FindPickupIndex(suppressedIndex); + transformationMap.Add(suppressedIndex, transformedIndex); + suppressedInventory.GiveItem(suppressedIndex); + Run.instance.DisableItemDrop(suppressedIndex); + if (flag) + { + Run.instance.EnableItemDrop(itemIndex); + } + if (transformedIndex != ItemIndex.None) + { + Inventory[] array = UnityEngine.Object.FindObjectsOfType(); + foreach (Inventory inventory in array) + { + if ((object)inventory != suppressedInventory) + { + TransformItem(inventory, suppressedIndex, transformedIndex); + } + } + } + ChestBehavior[] array2 = UnityEngine.Object.FindObjectsOfType(); + foreach (ChestBehavior chestBehavior in array2) + { + if (chestBehavior.HasRolledPickup(pickupIndex)) + { + chestBehavior.Roll(); + } + } + OptionChestBehavior[] array3 = UnityEngine.Object.FindObjectsOfType(); + foreach (OptionChestBehavior optionChestBehavior in array3) + { + if (optionChestBehavior.HasRolledPickup(pickupIndex)) + { + optionChestBehavior.Roll(); + } + } + ShopTerminalBehavior[] array4 = UnityEngine.Object.FindObjectsOfType(); + foreach (ShopTerminalBehavior shopTerminalBehavior in array4) + { + if (shopTerminalBehavior.CurrentPickupIndex() == pickupIndex) + { + shopTerminalBehavior.GenerateNewPickupServer(); + } + } + VoidSuppressorBehavior[] array5 = UnityEngine.Object.FindObjectsOfType(); + for (int i = 0; i < array5.Length; i++) + { + array5[i].RefreshItems(); + } + return true; + } + } + } + return false; + } + + private static void OnRunStart(Run run) + { + if (NetworkServer.active) + { + transformationMap = new Dictionary(); + suppressedInventory = UnityEngine.Object.Instantiate(networkedInventoryPrefab).GetComponent(); + NetworkServer.Spawn(suppressedInventory.gameObject); + } + } + + private static void OnRunDestroyGlobal(Run run) + { + if ((bool)suppressedInventory) + { + NetworkServer.Destroy(suppressedInventory.gameObject); + } + suppressedInventory = null; + } + + private static void TransformItem(Inventory inventory, ItemIndex suppressedIndex, ItemIndex transformedIndex) + { + int itemCount = inventory.GetItemCount(suppressedIndex); + if (itemCount > 0) + { + inventory.RemoveItem(suppressedIndex, itemCount); + inventory.GiveItem(transformedIndex, itemCount); + CharacterMaster component = inventory.GetComponent(); + if ((bool)component) + { + CharacterMasterNotificationQueue.SendTransformNotification(component, suppressedIndex, transformedIndex, CharacterMasterNotificationQueue.TransformationType.Suppressed); + } + } + } + + private static void StaticFixedUpdate() + { + foreach (Inventory pendingTransformationInventory in pendingTransformationInventories) + { + foreach (KeyValuePair item in transformationMap) + { + if (item.Value != ItemIndex.None) + { + TransformItem(pendingTransformationInventory, item.Key, item.Value); + } + } + } + pendingTransformationInventories.Clear(); + } + + private static void OnInventoryChangedGlobal(Inventory inventory) + { + if ((object)inventory == suppressedInventory || pendingTransformationInventories.Contains(inventory)) + { + return; + } + foreach (KeyValuePair item in transformationMap) + { + if (item.Value != ItemIndex.None && inventory.GetItemCount(item.Key) > 0) + { + pendingTransformationInventories.Add(inventory); + break; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/TeamSizeDamageBonusBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/TeamSizeDamageBonusBodyBehavior.cs new file mode 100644 index 0000000..8c42289 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/TeamSizeDamageBonusBodyBehavior.cs @@ -0,0 +1,38 @@ +namespace RoR2.Items; + +public class TeamSizeDamageBonusBodyBehavior : BaseItemBodyBehavior +{ + [ItemDefAssociation(useOnServer = true, useOnClient = true)] + private static ItemDef GetItemDef() + { + return RoR2Content.Items.TeamSizeDamageBonus; + } + + private void OnJoinTeamGlobal(TeamComponent teamComponent, TeamIndex newTeamIndex) + { + if ((object)teamComponent == base.body.teamComponent || newTeamIndex == base.body.teamComponent.teamIndex) + { + base.body.MarkAllStatsDirty(); + } + } + + private void OnLeaveTeamGlobal(TeamComponent teamComponent, TeamIndex oldTeamIndex) + { + if ((object)teamComponent == base.body.teamComponent || oldTeamIndex == base.body.teamComponent.teamIndex) + { + base.body.MarkAllStatsDirty(); + } + } + + private void OnEnable() + { + TeamComponent.onJoinTeamGlobal += OnJoinTeamGlobal; + TeamComponent.onLeaveTeamGlobal += OnLeaveTeamGlobal; + } + + private void OnDisable() + { + TeamComponent.onJoinTeamGlobal -= OnJoinTeamGlobal; + TeamComponent.onLeaveTeamGlobal -= OnLeaveTeamGlobal; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/UseAmbientLevelManager.cs b/ilspy_dump/ror2_csproj/RoR2.Items/UseAmbientLevelManager.cs new file mode 100644 index 0000000..aab53dd --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/UseAmbientLevelManager.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.ObjectModel; + +namespace RoR2.Items; + +public class UseAmbientLevelManager +{ + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + Run.onRunAmbientLevelUp += OnRunAmbientLevelUp; + } + + private static void OnRunAmbientLevelUp(Run run) + { + ReadOnlyCollection readOnlyInstancesList = CharacterBody.readOnlyInstancesList; + int i = 0; + for (int count = readOnlyInstancesList.Count; i < count; i++) + { + CharacterBody characterBody = readOnlyInstancesList[i]; + Inventory inventory = characterBody.inventory; + if ((bool)inventory && inventory.GetItemCount(RoR2Content.Items.UseAmbientLevel) > 0) + { + characterBody.MarkAllStatsDirty(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/WarCryOnCombatBodyBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Items/WarCryOnCombatBodyBehavior.cs new file mode 100644 index 0000000..f29ce27 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/WarCryOnCombatBodyBehavior.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace RoR2.Items; + +public class WarCryOnCombatBodyBehavior : BaseItemBodyBehavior +{ + private static readonly float warCryChargeDuration = 30f; + + private float warCryTimer; + + private GameObject warCryAuraController; + + private bool wasOutOfCombat; + + [ItemDefAssociation(useOnServer = true, useOnClient = false)] + private static ItemDef GetItemDef() + { + return JunkContent.Items.WarCryOnCombat; + } + + private void OnEnable() + { + warCryTimer = warCryChargeDuration; + } + + private void FixedUpdate() + { + warCryTimer -= Time.fixedDeltaTime; + if (warCryTimer <= 0f && !base.body.outOfCombat && wasOutOfCombat) + { + warCryTimer = warCryChargeDuration; + ActivateWarCryAura(stack); + } + wasOutOfCombat = base.body.outOfCombat; + } + + private void ActivateWarCryAura(int stacks) + { + if ((bool)warCryAuraController) + { + Object.Destroy(warCryAuraController); + } + warCryAuraController = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/WarCryAura"), base.transform.position, base.transform.rotation, base.transform); + warCryAuraController.GetComponent().teamIndex = base.body.teamComponent.teamIndex; + BuffWard component = warCryAuraController.GetComponent(); + component.expireDuration = 2f + 4f * (float)stacks; + component.Networkradius = 8f + 4f * (float)stacks; + warCryAuraController.GetComponent().AttachToGameObjectAndSpawn(base.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Items/WardOnLevelManager.cs b/ilspy_dump/ror2_csproj/RoR2.Items/WardOnLevelManager.cs new file mode 100644 index 0000000..cfb66ce --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Items/WardOnLevelManager.cs @@ -0,0 +1,40 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Items; + +public static class WardOnLevelManager +{ + private static GameObject wardPrefab; + + [SystemInitializer(new Type[] { typeof(ItemCatalog) })] + private static void Init() + { + GlobalEventManager.onCharacterLevelUp += OnCharacterLevelUp; + LegacyResourcesAPI.LoadAsyncCallback("Prefabs/NetworkedObjects/WarbannerWard", delegate(GameObject operationResult) + { + wardPrefab = operationResult; + }); + } + + private static void OnCharacterLevelUp(CharacterBody characterBody) + { + if (!NetworkServer.active) + { + return; + } + Inventory inventory = characterBody.inventory; + if ((bool)inventory) + { + int itemCount = inventory.GetItemCount(RoR2Content.Items.WardOnLevel); + if (itemCount > 0) + { + GameObject gameObject = UnityEngine.Object.Instantiate(wardPrefab, characterBody.transform.position, Quaternion.identity); + gameObject.GetComponent().teamIndex = characterBody.teamComponent.teamIndex; + gameObject.GetComponent().Networkradius = 8f + 8f * (float)itemCount; + NetworkServer.Spawn(gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/ClearLayerWeight.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/ClearLayerWeight.cs new file mode 100644 index 0000000..c4be908 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/ClearLayerWeight.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class ClearLayerWeight : StateMachineBehaviour +{ + public bool resetOnExit = true; + + public string layerName; + + public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateEnter(animator, stateInfo, layerIndex); + int layerIndex2 = layerIndex; + if (layerName.Length > 0) + { + layerIndex2 = animator.GetLayerIndex(layerName); + } + animator.SetLayerWeight(layerIndex2, 0f); + } + + public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateExit(animator, stateInfo, layerIndex); + if (resetOnExit) + { + int layerIndex2 = layerIndex; + if (layerName.Length > 0) + { + layerIndex2 = animator.GetLayerIndex(layerName); + } + animator.SetLayerWeight(layerIndex2, 1f); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/ClockParamWriter.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/ClockParamWriter.cs new file mode 100644 index 0000000..eb790be --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/ClockParamWriter.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +namespace RoR2.Mecanim; + +public class ClockParamWriter : StateMachineBehaviour +{ + public string targetParamName = "time"; + + public float cyclesPerDay = 2f; + + private const float secondsPerDay = 86400f; + + public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateUpdate(animator, stateInfo, layerIndex); + float num = 0f; + num = ((!Run.instance) ? ((float)(DateTime.Now - DateTime.Today).TotalSeconds) : Run.instance.GetRunStopwatch()); + animator.SetFloat(targetParamName, cyclesPerDay * num / 86400f); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/CrouchMecanim.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/CrouchMecanim.cs new file mode 100644 index 0000000..ae23c18 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/CrouchMecanim.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class CrouchMecanim : MonoBehaviour +{ + public float duckHeight; + + public Animator animator; + + public float smoothdamp; + + public float initialVerticalOffset; + + public Transform crouchOriginOverride; + + private float crouchCycle; + + private const float crouchRaycastFrequency = 2f; + + private float crouchStopwatch; + + private static readonly int crouchCycleOffsetParamNameHash = Animator.StringToHash("crouchCycleOffset"); + + private void FixedUpdate() + { + crouchStopwatch -= Time.fixedDeltaTime; + if (crouchStopwatch <= 0f) + { + crouchStopwatch = 0.5f; + Transform transform = (crouchOriginOverride ? crouchOriginOverride : base.transform); + Vector3 up = transform.up; + RaycastHit hitInfo; + bool flag = Physics.Raycast(new Ray(transform.position - up * initialVerticalOffset, up), out hitInfo, duckHeight + initialVerticalOffset, LayerIndex.world.mask, QueryTriggerInteraction.Ignore); + crouchCycle = (flag ? Mathf.Clamp01(1f - (hitInfo.distance - initialVerticalOffset) / duckHeight) : 0f); + } + } + + private void Update() + { + if ((bool)animator) + { + animator.SetFloat(crouchCycleOffsetParamNameHash, crouchCycle, smoothdamp, Time.deltaTime); + } + } + + private void OnDrawGizmos() + { + Gizmos.color = Color.yellow; + Gizmos.DrawLine(base.transform.position, base.transform.position + base.transform.up * duckHeight); + Gizmos.color = Color.red; + Gizmos.DrawLine(base.transform.position, base.transform.position + -base.transform.up * initialVerticalOffset); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/PlaySoundOnEnter.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/PlaySoundOnEnter.cs new file mode 100644 index 0000000..8244bb3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/PlaySoundOnEnter.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class PlaySoundOnEnter : StateMachineBehaviour +{ + public string soundString; + + public string stopSoundString; + + public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateEnter(animator, stateInfo, layerIndex); + Util.PlaySound(soundString, animator.gameObject); + } + + public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateEnter(animator, stateInfo, layerIndex); + Util.PlaySound(stopSoundString, animator.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/RandomBlinkController.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/RandomBlinkController.cs new file mode 100644 index 0000000..b8a0d1a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/RandomBlinkController.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class RandomBlinkController : MonoBehaviour +{ + public Animator animator; + + public string[] blinkTriggers; + + public float blinkChancePerUpdate; + + private float stopwatch; + + private const float updateFrequency = 4f; + + private void FixedUpdate() + { + stopwatch += Time.fixedDeltaTime; + if (!(stopwatch >= 0.25f)) + { + return; + } + stopwatch = 0f; + for (int i = 0; i < blinkTriggers.Length; i++) + { + if (Util.CheckRoll(blinkChancePerUpdate)) + { + animator.SetTrigger(blinkTriggers[i]); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/ResetFootsteps.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/ResetFootsteps.cs new file mode 100644 index 0000000..a33cdb2 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/ResetFootsteps.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class ResetFootsteps : StateMachineBehaviour +{ + public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + _ = (bool)animator.GetComponent(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/SetCorrectiveLayer.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/SetCorrectiveLayer.cs new file mode 100644 index 0000000..9659331 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/SetCorrectiveLayer.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class SetCorrectiveLayer : StateMachineBehaviour +{ + public string referenceOverrideLayerName; + + public float maxWeight = 1f; + + private float smoothVelocity; + + public override void OnStateMachineEnter(Animator animator, int stateMachinePathHash) + { + base.OnStateMachineEnter(animator, stateMachinePathHash); + } + + public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + int layerIndex2 = animator.GetLayerIndex(referenceOverrideLayerName); + float target = Mathf.Min(animator.GetLayerWeight(layerIndex2), maxWeight); + float weight = Mathf.SmoothDamp(animator.GetLayerWeight(layerIndex), target, ref smoothVelocity, 0.2f); + animator.SetLayerWeight(layerIndex, weight); + base.OnStateUpdate(animator, stateInfo, layerIndex); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/SetRandomIntOnEnter.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/SetRandomIntOnEnter.cs new file mode 100644 index 0000000..8cc0967 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/SetRandomIntOnEnter.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class SetRandomIntOnEnter : StateMachineBehaviour +{ + public string intParameterName; + + public int rangeMin; + + public int rangeMax; + + public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateEnter(animator, stateInfo, layerIndex); + animator.SetInteger(intParameterName, Random.Range(rangeMin, rangeMax + 1)); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Mecanim/StayInStateForDuration.cs b/ilspy_dump/ror2_csproj/RoR2.Mecanim/StayInStateForDuration.cs new file mode 100644 index 0000000..135083a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Mecanim/StayInStateForDuration.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace RoR2.Mecanim; + +public class StayInStateForDuration : StateMachineBehaviour +{ + [Tooltip("The reference float - this is how long we will stay in this state")] + public string durationFloatParameterName; + + private int durationFloatParameterHash; + + [Tooltip("The counter float - this is exposed incase we want to reset it")] + public string stopwatchFloatParameterName; + + private int stopwatchFloatParameterHash; + + [Tooltip("The bool that will be set to 'false' once the duration is up, and 'true' when entering this state.")] + public string deactivationBoolParameterName; + + private int deactivationBoolParameterHash; + + public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + base.OnStateEnter(animator, stateInfo, layerIndex); + durationFloatParameterHash = Animator.StringToHash(durationFloatParameterName); + stopwatchFloatParameterHash = Animator.StringToHash(stopwatchFloatParameterName); + deactivationBoolParameterHash = Animator.StringToHash(deactivationBoolParameterName); + animator.SetBool(deactivationBoolParameterHash, value: true); + } + + public override void OnStateUpdate(Animator animator, AnimatorStateInfo animatorStateInfo, int layerIndex) + { + base.OnStateUpdate(animator, animatorStateInfo, layerIndex); + float @float = animator.GetFloat(stopwatchFloatParameterHash); + float float2 = animator.GetFloat(durationFloatParameterHash); + @float += Time.deltaTime; + if (@float >= float2) + { + animator.SetFloat(stopwatchFloatParameterHash, 0f); + animator.SetBool(deactivationBoolParameterHash, value: false); + } + else + { + animator.SetFloat(stopwatchFloatParameterHash, @float); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Modding/LegacyModContentPackProvider.cs b/ilspy_dump/ror2_csproj/RoR2.Modding/LegacyModContentPackProvider.cs new file mode 100644 index 0000000..21a6e86 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Modding/LegacyModContentPackProvider.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using RoR2.ContentManagement; +using UnityEngine; + +namespace RoR2.Modding; + +public class LegacyModContentPackProvider : IContentPackProvider +{ + private ContentPack finalizedContentPack; + + public static LegacyModContentPackProvider instance { get; private set; } = new LegacyModContentPackProvider(); + + + public ContentPack registrationContentPack { get; private set; } + + public bool cutoffReached { get; private set; } + + public string identifier => "RoR2.LegacyModContent"; + + private LegacyModContentPackProvider() + { + registrationContentPack = new ContentPack(); + finalizedContentPack = new ContentPack(); + ContentManager.collectContentPackProviders += delegate(ContentManager.AddContentPackProviderDelegate addContentPackProvider) + { + addContentPackProvider(this); + }; + } + + public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) + { + ContentPack.Copy(registrationContentPack, finalizedContentPack); + yield break; + } + + public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) + { + ContentPack.Copy(finalizedContentPack, args.output); + yield break; + } + + public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) + { + ContentPack.Copy(new ContentPack(), registrationContentPack); + finalizedContentPack = null; + yield break; + } + + public void HandleLegacyGetAdditionalEntries(string eventName, Action> callback, NamedAssetCollection dest) + { + if (cutoffReached) + { + throw new InvalidOperationException("Legacy mod ContentPack has been finalized. It is too late to add additional entries via " + eventName + "."); + } + List list = new List(); + try + { + callback?.Invoke(list); + dest.Add(list.ToArray()); + Debug.LogWarning("Added content to legacy mod ContentPack via " + eventName + " succeeded. Do not use this code path; it will be removed in a future update. Use IContentPackProvider instead."); + } + catch (Exception arg) + { + Debug.LogError($"Adding content to legacy mod ContentPack via {eventName} failed: {arg}."); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Modding/RoR2Mod.cs b/ilspy_dump/ror2_csproj/RoR2.Modding/RoR2Mod.cs new file mode 100644 index 0000000..db254cd --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Modding/RoR2Mod.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; +using RoR2.ContentManagement; + +namespace RoR2.Modding; + +public class RoR2Mod +{ + [NotNull] + public readonly Mod mod; + + public IContentPackProvider contentPackProvider; + + public RoR2Mod([NotNull] Mod mod) + { + this.mod = mod; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMap.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMap.cs new file mode 100644 index 0000000..4644a81 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMap.cs @@ -0,0 +1,581 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using HG; +using Unity.Collections; +using UnityEngine; + +namespace RoR2.Navigation; + +public class BlockMap where TItemPositionGetter : IPosition3Getter +{ + private struct ItemDistanceSqrPair + { + public int itemIndex; + + public float distanceSqr; + } + + private interface ISearchResultHandler + { + bool OnEncounterResult(TItem result); + } + + private struct SingleSearchResultHandler : ISearchResultHandler + { + public bool foundResult { get; private set; } + + public TItem result { get; private set; } + + public bool OnEncounterResult(TItem result) + { + foundResult = true; + this.result = result; + return false; + } + } + + private struct ListWriteSearchResultHandler : ISearchResultHandler + { + private readonly List dest; + + public ListWriteSearchResultHandler(List dest) + { + this.dest = dest; + } + + public bool OnEncounterResult(TItem result) + { + dest.Add(result); + return true; + } + } + + private struct GridEnumerator + { + private readonly Vector3Int startPos; + + private readonly Vector3Int endPos; + + private Vector3Int _current; + + public Vector3Int Current => _current; + + public GridEnumerator(in Vector3Int startCellIndex, in Vector3Int endCellIndex) + { + startPos = startCellIndex; + endPos = endCellIndex; + _current = startCellIndex; + ref Vector3Int current = ref _current; + int x = current.x - 1; + current.x = x; + } + + public bool MoveNext() + { + if (++_current.x >= endPos.x) + { + _current.x = startPos.x; + if (++_current.z >= endPos.z) + { + _current.z = startPos.z; + if (++_current.y >= endPos.y) + { + _current.y = startPos.y; + return false; + } + } + } + return true; + } + + public void Reset() + { + _current = startPos; + } + } + + private struct GridEnumerable + { + private readonly Vector3Int startPos; + + private readonly Vector3Int endPos; + + public GridEnumerable(Vector3Int startPos, Vector3Int endPos) + { + this.startPos = startPos; + this.endPos = endPos; + } + + public GridEnumerator GetEnumerator() + { + return new GridEnumerator(in startPos, in endPos); + } + } + + private const bool debugDraw = false; + + private const bool aggressiveDebug = false; + + private Vector3 cellSize; + + private Vector3 invCellSize; + + private Bounds worldBoundingBox; + + private BlockMapCell[] cells = Array.Empty(); + + private int cellCount1D; + + private Vector3Int cellCounts; + + private TItem[] itemsPackedByCell = Array.Empty(); + + private int itemCount; + + private TItemPositionGetter itemPositionGetter; + + public BlockMap() + : this(new Vector3(15f, 30f, 15f)) + { + } + + public BlockMap(Vector3 cellSize) + { + SetCellSize(cellSize); + } + + public void Reset() + { + worldBoundingBox = default(Bounds); + ArrayUtils.Clear(itemsPackedByCell, ref itemCount); + cellCounts = Vector3Int.zero; + cellCount1D = 0; + } + + public void SetCellSize(Vector3 newSize) + { + if (cellSize != newSize) + { + cellSize = newSize; + invCellSize = new Vector3(1f / cellSize.x, 1f / cellSize.y, 1f / cellSize.z); + Reset(); + } + } + + public void Set(T newItems, int newItemsLength, TItemPositionGetter newItemPositionGetter) where T : IList + { + Reset(); + NativeArray nativeArray = new NativeArray(newItemsLength, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + try + { + itemPositionGetter = newItemPositionGetter; + if (newItems.Count > 0) + { + worldBoundingBox = new Bounds(itemPositionGetter.GetPosition3(newItems[0]), Vector3.zero); + for (int i = 1; i < newItems.Count; i++) + { + worldBoundingBox.Encapsulate(itemPositionGetter.GetPosition3(newItems[i])); + } + } + worldBoundingBox.min -= Vector3.one; + worldBoundingBox.max += Vector3.one; + Vector3 size = worldBoundingBox.size; + cellCounts = Vector3Int.Max(Vector3Int.CeilToInt(Vector3.Scale(size, invCellSize)), Vector3Int.one); + cellCount1D = cellCounts.x * cellCounts.y * cellCounts.z; + Array.Resize(ref cells, cellCount1D); + Array.Clear(cells, 0, cells.Length); + _ = worldBoundingBox.min; + for (int j = 0; j < newItems.Count; j++) + { + Vector3 worldPosition = itemPositionGetter.GetPosition3(newItems[j]); + Vector3Int gridPos = WorldPositionToGridPosFloor(in worldPosition); + BlockMapCellIndex blockMapCellIndex2 = (nativeArray[j] = GridPosToCellIndex(in gridPos)); + cells[(int)blockMapCellIndex2].itemCount++; + } + int num = 0; + for (int k = 0; k < cells.Length; k++) + { + ref BlockMapCell reference = ref cells[k]; + reference.itemStartIndex = num; + num += reference.itemCount; + } + itemCount = newItems.Count; + ArrayUtils.EnsureCapacity(ref itemsPackedByCell, itemCount); + NativeArray nativeArray2 = new NativeArray(cells.Length, Allocator.Temp); + for (int l = 0; l < itemCount; l++) + { + BlockMapCellIndex blockMapCellIndex3 = nativeArray[l]; + ref BlockMapCell reference2 = ref cells[(int)blockMapCellIndex3]; + TItem val = newItems[l]; + int num2 = nativeArray2[(int)blockMapCellIndex3]++; + itemsPackedByCell[reference2.itemStartIndex + num2] = val; + } + nativeArray2.Dispose(); + } + catch + { + Reset(); + throw; + } + finally + { + nativeArray.Dispose(); + } + } + + private Vector3Int WorldPositionToGridPosFloor(in Vector3 worldPosition) + { + Vector3 localPosition = worldPosition - worldBoundingBox.min; + return LocalPositionToGridPosFloor(in localPosition); + } + + private Vector3Int WorldPositionToGridPosCeil(in Vector3 worldPosition) + { + Vector3 localPosition = worldPosition - worldBoundingBox.min; + return LocalPositionToGridPosCeil(in localPosition); + } + + private Vector3Int LocalPositionToGridPosFloor(in Vector3 localPosition) + { + return Vector3Int.FloorToInt(Vector3.Scale(localPosition, invCellSize)); + } + + private Vector3Int LocalPositionToGridPosCeil(in Vector3 localPosition) + { + return Vector3Int.CeilToInt(Vector3.Scale(localPosition, invCellSize)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private BlockMapCellIndex GridPosToCellIndex(in Vector3Int gridPos) + { + return (BlockMapCellIndex)((gridPos.y * cellCounts.z + gridPos.z) * cellCounts.x + gridPos.x); + } + + private Vector3Int CellIndexToGridPos(BlockMapCellIndex cellIndex) + { + int num = (int)cellIndex; + Vector3Int zero = Vector3Int.zero; + int num2 = cellCounts.x * cellCounts.z; + zero.y = num / num2; + num -= zero.y * num2; + zero.z = num / cellCounts.x; + num -= zero.z * cellCounts.x; + zero.x = num; + return zero; + } + + private Bounds GridPosToBounds(in Vector3Int gridPos) + { + Vector3 vector = gridPos; + vector.Scale(cellSize); + vector += worldBoundingBox.min; + Bounds result = default(Bounds); + result.SetMinMax(vector, vector + cellSize); + return result; + } + + private bool GridPosIsValid(Vector3Int gridPos) + { + if (gridPos.x >= 0 && gridPos.y >= 0 && gridPos.z >= 0 && gridPos.x < cellCounts.x && gridPos.y < cellCounts.y) + { + return gridPos.z < cellCounts.z; + } + return false; + } + + public void GetItemsInSphere(Vector3 point, float radius, List dest) + { + Bounds bounds = GetSphereBounds(point, radius); + int count = dest.Count; + GetBoundOverlappingCellItems(in bounds, dest); + float num = radius * radius; + for (int num2 = dest.Count - 1; num2 >= count; num2--) + { + TItem item = dest[num2]; + if ((itemPositionGetter.GetPosition3(item) - point).sqrMagnitude > num) + { + dest.RemoveAt(num2); + } + } + } + + public void GetItemsInBounds(in Bounds bounds, List dest) + { + int count = dest.Count; + GetBoundOverlappingCellItems(in bounds, dest); + for (int num = dest.Count - 1; num >= count; num--) + { + TItem item = dest[num]; + Vector3 position = itemPositionGetter.GetPosition3(item); + if (!worldBoundingBox.Contains(position)) + { + dest.RemoveAt(num); + } + } + } + + private void GetBoundOverlappingCellItems(in Bounds bounds, List dest) + { + List list = CollectionPool>.RentCollection(); + GetBoundOverlappingCells(bounds, list); + foreach (BlockMapCellIndex item in list) + { + ref BlockMapCell reference = ref cells[(int)item]; + int i = reference.itemStartIndex; + for (int num = reference.itemStartIndex + reference.itemCount; i < num; i++) + { + dest.Add(itemsPackedByCell[i]); + } + } + list = CollectionPool>.ReturnCollection(list); + } + + private void GetBoundOverlappingCells(Bounds bounds, List dest) + { + Vector3 worldPosition = bounds.min; + Vector3Int vector3Int = WorldPositionToGridPosFloor(in worldPosition); + worldPosition = bounds.max; + Vector3Int vector3Int2 = WorldPositionToGridPosCeil(in worldPosition); + vector3Int.Clamp(Vector3Int.zero, cellCounts); + vector3Int2.Clamp(Vector3Int.zero, cellCounts); + Vector3Int gridPos = vector3Int; + gridPos.y = vector3Int.y; + while (gridPos.y < vector3Int2.y) + { + gridPos.z = vector3Int.z; + int x; + while (gridPos.z < vector3Int2.z) + { + gridPos.x = vector3Int.x; + while (gridPos.x < vector3Int2.x) + { + dest.Add(GridPosToCellIndex(in gridPos)); + x = gridPos.x + 1; + gridPos.x = x; + } + x = gridPos.z + 1; + gridPos.z = x; + } + x = gridPos.y + 1; + gridPos.y = x; + } + } + + public bool GetNearestItemWhichPassesFilter(Vector3 position, float maxDistance, ref TItemFilter filter, out TItem dest) where TItemFilter : IBlockMapSearchFilter + { + SingleSearchResultHandler searchResultHandler = default(SingleSearchResultHandler); + GetNearestItemsWhichPassFilter(position, maxDistance, ref filter, ref searchResultHandler); + dest = (searchResultHandler.foundResult ? searchResultHandler.result : default(TItem)); + return searchResultHandler.foundResult; + } + + public void GetNearestItemsWhichPassFilter(Vector3 position, float maxDistance, ref TItemFilter filter, List dest) where TItemFilter : IBlockMapSearchFilter + { + ListWriteSearchResultHandler searchResultHandler = new ListWriteSearchResultHandler(dest); + GetNearestItemsWhichPassFilter(position, maxDistance, ref filter, ref searchResultHandler); + } + + private void GetNearestItemsWhichPassFilter(Vector3 position, float maxDistance, ref TItemFilter filter, ref TSearchResultHandler searchResultHandler) where TItemFilter : IBlockMapSearchFilter where TSearchResultHandler : ISearchResultHandler + { + maxDistance = Mathf.Max(maxDistance, 0f); + List candidatesInsideRadius = CollectionPool>.RentCollection(); + List candidatesOutsideRadius = CollectionPool>.RentCollection(); + float radiusSqr; + try + { + Vector3Int gridPos = WorldPositionToGridPosFloor(in position); + Bounds bounds = GridPosToBounds(in gridPos); + Bounds currentBounds = bounds; + float additionalRadius2 = cellSize.ComponentMin(); + float radius = DistanceToNearestWall(in position, in currentBounds); + radiusSqr = radius * radius; + BlockMapCellIndex cellIndex2 = GridPosToCellIndex(in gridPos); + BoundsInt visitedCells = new BoundsInt(gridPos, Vector3Int.one); + int visitedCellCount = 0; + bool num = GridPosIsValid(gridPos); + if (num) + { + VisitCell(cellIndex2); + } + if (!num) + { + AddRadius(Mathf.Sqrt(worldBoundingBox.SqrDistance(position))); + } + bool flag = true; + while (flag) + { + while (candidatesInsideRadius.Count > 0) + { + int num2 = -1; + float num3 = float.PositiveInfinity; + for (int i = 0; i < candidatesInsideRadius.Count; i++) + { + ItemDistanceSqrPair itemDistanceSqrPair = candidatesInsideRadius[i]; + if (itemDistanceSqrPair.distanceSqr < num3) + { + num3 = itemDistanceSqrPair.distanceSqr; + num2 = i; + } + } + if (num2 != -1) + { + ItemDistanceSqrPair itemDistanceSqrPair2 = candidatesInsideRadius[num2]; + candidatesInsideRadius.RemoveAt(num2); + bool shouldFinish = false; + if ((filter.CheckItem(itemsPackedByCell[itemDistanceSqrPair2.itemIndex], ref shouldFinish) && !searchResultHandler.OnEncounterResult(itemsPackedByCell[itemDistanceSqrPair2.itemIndex])) || shouldFinish) + { + return; + } + } + } + flag = AddRadius(additionalRadius2); + } + bool AddRadius(float additionalRadius) + { + radius += additionalRadius; + bool flag2 = radius >= maxDistance; + if (flag2) + { + radius = maxDistance; + } + radiusSqr = radius * radius; + currentBounds = GetSphereBounds(position, radius); + for (int num4 = candidatesOutsideRadius.Count - 1; num4 >= 0; num4--) + { + ItemDistanceSqrPair item = candidatesOutsideRadius[num4]; + if (item.distanceSqr < radiusSqr) + { + candidatesOutsideRadius.RemoveAt(num4); + candidatesInsideRadius.Add(item); + } + } + bool flag3 = visitedCellCount >= cellCount1D; + if (!flag3) + { + BoundsInt outer = WorldBoundsToOverlappingGridBoundsClamped(currentBounds); + BoundsIntDifferenceEnumerable.BoundsIntDifferenceEnumerator enumerator = new BoundsIntDifferenceEnumerable(in outer, in visitedCells).GetEnumerator(); + while (enumerator.MoveNext()) + { + Vector3Int gridPos2 = enumerator.Current; + VisitCell(GridPosToCellIndex(in gridPos2)); + } + visitedCells = outer; + } + if (candidatesInsideRadius.Count == 0) + { + if (flag2) + { + return false; + } + if (flag3 && candidatesOutsideRadius.Count == 0) + { + return false; + } + } + return true; + } + void VisitCell(BlockMapCellIndex cellIndex) + { + int num5 = visitedCellCount + 1; + visitedCellCount = num5; + ref BlockMapCell reference = ref cells[(int)cellIndex]; + int j = reference.itemStartIndex; + for (int num6 = reference.itemStartIndex + reference.itemCount; j < num6; j++) + { + VisitItem(j); + } + } + } + finally + { + candidatesOutsideRadius = CollectionPool>.ReturnCollection(candidatesOutsideRadius); + candidatesInsideRadius = CollectionPool>.ReturnCollection(candidatesInsideRadius); + } + void VisitItem(int itemIndex) + { + Vector3 position2 = itemPositionGetter.GetPosition3(itemsPackedByCell[itemIndex]); + ItemDistanceSqrPair itemDistanceSqrPair3 = default(ItemDistanceSqrPair); + itemDistanceSqrPair3.itemIndex = itemIndex; + itemDistanceSqrPair3.distanceSqr = (position2 - position).sqrMagnitude; + ItemDistanceSqrPair item2 = itemDistanceSqrPair3; + ((item2.distanceSqr < radiusSqr) ? candidatesInsideRadius : candidatesOutsideRadius).Add(item2); + } + } + + private float DistanceToNearestWall(in Vector3 position, in Bounds bounds) + { + Vector3 vector = position - bounds.min; + Vector3 vector2 = bounds.max - position; + float x = vector.x; + x = ((x < vector.y) ? x : vector.y); + x = ((x < vector.z) ? x : vector.z); + x = ((x < vector2.x) ? x : vector2.x); + x = ((x < vector2.y) ? x : vector2.y); + return (x < vector2.z) ? x : vector2.z; + } + + private float DistanceToNearestWall(in Bounds innerBounds, in Bounds outerBounds) + { + Vector3 vector = innerBounds.min - outerBounds.min; + Vector3 vector2 = outerBounds.max - innerBounds.max; + float x = vector.x; + x = ((x < vector.y) ? x : vector.y); + x = ((x < vector.z) ? x : vector.z); + x = ((x < vector2.x) ? x : vector2.x); + x = ((x < vector2.y) ? x : vector2.y); + return (x < vector2.z) ? x : vector2.z; + } + + private static Bounds GetSphereBounds(Vector3 origin, float radius) + { + float num = radius * 2f; + return new Bounds(origin, new Vector3(num, num, num)); + } + + private BoundsInt WorldBoundsOverlappingToGridBounds(Bounds worldBounds) + { + Vector3 worldPosition = worldBounds.min; + Vector3Int minPosition = WorldPositionToGridPosFloor(in worldPosition); + worldPosition = worldBounds.max; + Vector3Int maxPosition = WorldPositionToGridPosCeil(in worldPosition); + BoundsInt result = default(BoundsInt); + result.SetMinMax(minPosition, maxPosition); + return result; + } + + private BoundsInt WorldBoundsToOverlappingGridBoundsClamped(Bounds worldBounds) + { + Vector3 worldPosition = worldBounds.min; + Vector3Int minPosition = WorldPositionToGridPosFloor(in worldPosition); + worldPosition = worldBounds.max; + Vector3Int maxPosition = WorldPositionToGridPosCeil(in worldPosition); + minPosition.Clamp(Vector3Int.zero, cellCounts); + maxPosition.Clamp(Vector3Int.zero, cellCounts); + BoundsInt result = default(BoundsInt); + result.SetMinMax(minPosition, maxPosition); + return result; + } + + private GridEnumerable ValidGridPositionsInBounds(Bounds bounds) + { + Vector3 worldPosition = bounds.min; + Vector3Int startPos = WorldPositionToGridPosFloor(in worldPosition); + worldPosition = bounds.max; + Vector3Int endPos = WorldPositionToGridPosCeil(in worldPosition); + startPos.Clamp(Vector3Int.zero, cellCounts); + endPos.Clamp(Vector3Int.zero, cellCounts); + return new GridEnumerable(startPos, endPos); + } + + private GridEnumerable ValidGridPositionsInBoundsWithExclusion(Bounds bounds, BoundsInt excludedCells) + { + Vector3 worldPosition = bounds.min; + Vector3Int startPos = WorldPositionToGridPosFloor(in worldPosition); + worldPosition = bounds.max; + Vector3Int endPos = WorldPositionToGridPosCeil(in worldPosition); + startPos.Clamp(Vector3Int.zero, cellCounts - Vector3Int.one); + endPos.Clamp(Vector3Int.zero, cellCounts - Vector3Int.one); + return new GridEnumerable(startPos, endPos); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMapCell.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMapCell.cs new file mode 100644 index 0000000..874c2d4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMapCell.cs @@ -0,0 +1,8 @@ +namespace RoR2.Navigation; + +internal struct BlockMapCell +{ + public int itemStartIndex; + + public int itemCount; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMapCellIndex.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMapCellIndex.cs new file mode 100644 index 0000000..80ba611 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/BlockMapCellIndex.cs @@ -0,0 +1,6 @@ +namespace RoR2.Navigation; + +internal enum BlockMapCellIndex +{ + Invalid = -1 +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/BroadNavigationSystem.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/BroadNavigationSystem.cs new file mode 100644 index 0000000..8a1630f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/BroadNavigationSystem.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using HG; +using UnityEngine; + +namespace RoR2.Navigation; + +public abstract class BroadNavigationSystem : IDisposable +{ + public enum AgentHandle + { + None = -1 + } + + protected struct BaseAgentData + { + public bool enabled; + + public bool isValid; + + public float localTime; + + public Vector3? currentPosition; + + public Vector3? goalPosition; + + public float maxWalkSpeed; + + public float maxSlopeAngle; + + public float maxJumpHeight; + } + + public struct AgentOutput + { + public float desiredJumpVelocity { get; set; } + + public Vector3? nextPosition { get; set; } + + public float lastPathUpdate { get; set; } + + public bool targetReachable { get; set; } + + public float time { get; set; } + } + + public readonly struct Agent + { + public static readonly Agent invalid = new Agent(null, AgentHandle.None); + + public readonly BroadNavigationSystem system; + + public readonly AgentHandle handle; + + private ref BaseAgentData agentData => ref system.allAgentData[(int)handle]; + + public bool enabled + { + get + { + return agentData.enabled; + } + set + { + agentData.enabled = value; + } + } + + public float maxSlopeAngle + { + get + { + return agentData.maxSlopeAngle; + } + set + { + agentData.maxSlopeAngle = value; + } + } + + public float maxWalkSpeed + { + get + { + return agentData.maxWalkSpeed; + } + set + { + agentData.maxWalkSpeed = value; + } + } + + public float maxJumpHeight + { + get + { + return agentData.maxJumpHeight; + } + set + { + agentData.maxJumpHeight = value; + } + } + + public Vector3? currentPosition + { + get + { + return agentData.currentPosition; + } + set + { + agentData.currentPosition = value; + } + } + + public Vector3? goalPosition + { + get + { + return agentData.goalPosition; + } + set + { + agentData.goalPosition = value; + } + } + + public AgentOutput output => system.agentOutputs[(int)handle]; + + public Agent(BroadNavigationSystem system, AgentHandle handle) + { + this.handle = handle; + this.system = system; + } + + public void ConfigureFromBody(CharacterBody body) + { + system.ConfigureAgentFromBodyInternal(in handle, body); + } + + public void InvalidatePath() + { + system.InvalidateAgentPathInternal(in handle); + } + } + + private static readonly List instancesList; + + private IndexAllocator agentIndexAllocator = new IndexAllocator(); + + private BaseAgentData[] allAgentData = Array.Empty(); + + private AgentOutput[] agentOutputs = Array.Empty(); + + protected float localTime; + + protected int agentCount { get; private set; } + + static BroadNavigationSystem() + { + instancesList = new List(); + RoR2Application.onFixedUpdate += StaticUpdate; + } + + private static void StaticUpdate() + { + if (Time.fixedDeltaTime == 0f) + { + return; + } + foreach (BroadNavigationSystem instances in instancesList) + { + instances.Update(Time.fixedDeltaTime); + } + } + + public BroadNavigationSystem() + { + instancesList.Add(this); + } + + public virtual void Dispose() + { + instancesList.Remove(this); + for (AgentHandle index = (AgentHandle)0; (int)index < allAgentData.Length; index++) + { + if (allAgentData[(int)index].isValid) + { + DestroyAgentInternal(in index); + } + } + } + + public void RequestAgent(ref Agent agent) + { + AgentHandle index = (AgentHandle)agentIndexAllocator.RequestIndex(); + CreateAgentInternal(in index); + agent = GetAgent(index); + } + + public void ReturnAgent(ref Agent agent) + { + DestroyAgentInternal(in agent.handle); + agentIndexAllocator.FreeIndex((int)agent.handle); + agent = Agent.invalid; + } + + public Agent GetAgent(AgentHandle agentHandle) + { + return new Agent(this, agentHandle); + } + + public bool IsValidHandle(in AgentHandle handle) + { + if (!ArrayUtils.IsInBounds(allAgentData, (int)handle)) + { + return false; + } + return allAgentData[(int)handle].isValid; + } + + public void GetAgentOutput(in AgentHandle handle, out AgentOutput output) + { + output = agentOutputs[(int)handle]; + } + + private void Update(float deltaTime) + { + localTime += deltaTime; + UpdateAgentsInternal(deltaTime); + } + + private void CreateAgentInternal(in AgentHandle index) + { + int num = agentCount + 1; + agentCount = num; + ArrayUtils.EnsureCapacity(ref allAgentData, agentCount); + ArrayUtils.EnsureCapacity(ref agentOutputs, agentCount); + ref BaseAgentData reference = ref allAgentData[(int)index]; + reference.isValid = true; + reference.localTime = 0f; + CreateAgent(in index); + } + + private void DestroyAgentInternal(in AgentHandle index) + { + DestroyAgent(in index); + allAgentData[(int)index] = default(BaseAgentData); + agentOutputs[(int)index] = default(AgentOutput); + int num = agentCount - 1; + agentCount = num; + } + + private void UpdateAgentsInternal(float deltaTime) + { + for (AgentHandle agentHandle = (AgentHandle)0; (int)agentHandle < allAgentData.Length; agentHandle++) + { + ref BaseAgentData reference = ref allAgentData[(int)agentHandle]; + if (reference.enabled) + { + reference.localTime += deltaTime; + } + } + UpdateAgents(deltaTime); + } + + private void ConfigureAgentFromBodyInternal(in AgentHandle index, CharacterBody body) + { + ref BaseAgentData reference = ref allAgentData[(int)index]; + reference.maxWalkSpeed = 0f; + reference.maxSlopeAngle = 0f; + reference.maxJumpHeight = 0f; + reference.currentPosition = null; + if ((bool)body) + { + reference.maxWalkSpeed = body.moveSpeed; + reference.maxSlopeAngle = body.characterMotor?.Motor.MaxStableSlopeAngle ?? 0f; + reference.maxJumpHeight = body.maxJumpHeight; + reference.currentPosition = body.footPosition; + } + ConfigureAgentFromBody(in index, body); + } + + private void InvalidateAgentPathInternal(in AgentHandle index) + { + InvalidateAgentPath(in index); + } + + protected ref readonly BaseAgentData GetAgentData(in AgentHandle agentHandle) + { + return ref allAgentData[(int)agentHandle]; + } + + protected void SetAgentOutput(in AgentHandle agentHandle, in AgentOutput output) + { + ref AgentOutput reference = ref agentOutputs[(int)agentHandle]; + reference = output; + reference.time = localTime; + } + + protected abstract void CreateAgent(in AgentHandle index); + + protected abstract void DestroyAgent(in AgentHandle index); + + protected abstract void UpdateAgents(float deltaTime); + + protected abstract void ConfigureAgentFromBody(in AgentHandle index, CharacterBody body); + + protected abstract void InvalidateAgentPath(in AgentHandle index); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/DisableWithGate.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/DisableWithGate.cs new file mode 100644 index 0000000..d987b11 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/DisableWithGate.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace RoR2.Navigation; + +public class DisableWithGate : MonoBehaviour +{ + public string gateToMatch; + + public bool invert; + + private void Start() + { + if ((bool)SceneInfo.instance && SceneInfo.instance.groundNodes.IsGateOpen(gateToMatch) == invert) + { + base.gameObject.SetActive(value: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/GateStateSetter.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/GateStateSetter.cs new file mode 100644 index 0000000..46fa41e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/GateStateSetter.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace RoR2.Navigation; + +public class GateStateSetter : MonoBehaviour +{ + public string gateToEnableWhenEnabled; + + public string gateToDisableWhenEnabled; + + private void OnEnable() + { + UpdateGates(enabledState: true); + } + + private void OnDisable() + { + UpdateGates(enabledState: false); + } + + private void UpdateGates(bool enabledState) + { + if ((bool)SceneInfo.instance) + { + if (!string.IsNullOrEmpty(gateToEnableWhenEnabled)) + { + SceneInfo.instance.SetGateState(gateToEnableWhenEnabled, enabledState); + } + if (!string.IsNullOrEmpty(gateToDisableWhenEnabled)) + { + SceneInfo.instance.SetGateState(gateToDisableWhenEnabled, !enabledState); + } + } + } + + [ContextMenu("ToggleGates as if Enabled")] + private void ToggleEnable() + { + UpdateGates(enabledState: true); + } + + [ContextMenu("ToggleGates as if Disabled")] + private void ToggleDisable() + { + UpdateGates(enabledState: false); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/IBlockMapSearchFilter.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/IBlockMapSearchFilter.cs new file mode 100644 index 0000000..d432a8f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/IBlockMapSearchFilter.cs @@ -0,0 +1,6 @@ +namespace RoR2.Navigation; + +public interface IBlockMapSearchFilter +{ + bool CheckItem(TItem item, ref bool shouldFinish); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/IPosition3Getter.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/IPosition3Getter.cs new file mode 100644 index 0000000..c1efb73 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/IPosition3Getter.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +namespace RoR2.Navigation; + +public interface IPosition3Getter +{ + Vector3 GetPosition3(T item); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNode.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNode.cs new file mode 100644 index 0000000..6cbaeef --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNode.cs @@ -0,0 +1,433 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using UnityEngine; + +namespace RoR2.Navigation; + +[ExecuteInEditMode] +public class MapNode : MonoBehaviour +{ + public struct Link + { + public MapNode nodeB; + + public float distanceScore; + + public float minJumpHeight; + + public int hullMask; + + public int jumpHullMask; + + public string gateName; + } + + public class MoveProbe + { + public CharacterController testCharacterController; + + private float testTimeStep = 1f / 15f; + + public void Init() + { + GameObject gameObject = new GameObject(); + gameObject.name = "NodeGraphProbe"; + _ = gameObject.transform; + testCharacterController = gameObject.AddComponent(); + testCharacterController.stepOffset = 0.5f; + testCharacterController.slopeLimit = 60f; + } + + public void SetHull(HullClassification hullClassification) + { + HullDef hullDef = HullDef.Find(hullClassification); + testCharacterController.radius = hullDef.radius; + testCharacterController.height = hullDef.height; + } + + public void Destroy() + { + Object.DestroyImmediate(testCharacterController.gameObject); + } + + private static float DistanceXZ(Vector3 a, Vector3 b) + { + a.y = 0f; + b.y = 0f; + return Vector3.Distance(a, b); + } + + public static Vector3 GetGroundPosition(Vector3 footPosition, float height, float radius) + { + Vector3 vector = Vector3.up * (height * 0.5f - radius); + Vector3 vector2 = Vector3.up * (height * 0.5f); + Vector3 vector3 = footPosition + vector2; + float num = radius * 0.5f + 0.005f; + Vector3 vector4 = footPosition + Vector3.up * num; + Vector3 vector5 = vector3 + Vector3.up * num; + if (Physics.CapsuleCast(vector5 + vector, vector5 - vector, radius, Vector3.down, out var hitInfo, num * 2f + 0.005f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + Vector3 vector6 = hitInfo.distance * Vector3.down; + return vector4 + vector6; + } + return footPosition; + } + + public Vector3 GetGroundPosition(Vector3 footPosition) + { + return GetGroundPosition(footPosition, testCharacterController.height, testCharacterController.radius); + } + + public bool CapsuleOverlapTest(Vector3 centerOfCapsule) + { + Vector3 vector = Vector3.up * (testCharacterController.height * 0.5f - testCharacterController.radius); + _ = Vector3.up * (testCharacterController.height * 0.5f); + return Physics.OverlapCapsule(centerOfCapsule + vector, centerOfCapsule - vector, testCharacterController.radius, (int)LayerIndex.world.mask | (int)LayerIndex.CommonMasks.characterBodiesOrDefault, QueryTriggerInteraction.Ignore).Length == 0; + } + + public bool FlyTest(Vector3 startPos, Vector3 endPos, float flySpeed) + { + Vector3 vector = Vector3.up * (testCharacterController.height * 0.5f - testCharacterController.radius); + return !Physics.CapsuleCast(startPos + vector, startPos - vector, testCharacterController.radius, (endPos - startPos).normalized, (endPos - startPos).magnitude, LayerIndex.world.mask); + } + + private void MoveCapsule(Vector3 displacement) + { + testCharacterController.Move(displacement); + } + + private void SetCapsulePosition(Vector3 position) + { + testCharacterController.transform.position = position; + Physics.SyncTransforms(); + } + + public bool GroundTest(Vector3 startCenterOfCapsulePos, Vector3 endCenterOfCapsulePos, float hSpeed) + { + MoveCapsule(Vector3.zero); + Vector3 zero = Vector3.zero; + float num = DistanceXZ(startCenterOfCapsulePos, endCenterOfCapsulePos); + SetCapsulePosition(startCenterOfCapsulePos + Vector3.up); + int num2 = Mathf.CeilToInt(num * 1.5f / hSpeed / testTimeStep); + Vector3 vector = testCharacterController.transform.position; + for (int i = 0; i < num2; i++) + { + Vector3 vector2 = endCenterOfCapsulePos - testCharacterController.transform.position; + if (vector2.sqrMagnitude <= 0.25f) + { + return true; + } + Vector3 vector3 = vector2; + vector3.y = 0f; + vector3.Normalize(); + zero.x = vector3.x * hSpeed; + zero.z = vector3.z * hSpeed; + zero += Physics.gravity * testTimeStep; + MoveCapsule(zero * testTimeStep); + Vector3 position = testCharacterController.transform.position; + if (position == vector) + { + return false; + } + vector = position; + } + return false; + } + + public float JumpTest(Vector3 startCenterOfCapsulePos, Vector3 endCenterOfCapsulePos, float hSpeed) + { + float y = Trajectory.CalculateInitialYSpeed(Trajectory.CalculateGroundTravelTime(hSpeed, DistanceXZ(startCenterOfCapsulePos, endCenterOfCapsulePos)), endCenterOfCapsulePos.y - startCenterOfCapsulePos.y); + testCharacterController.Move(Vector3.zero); + Vector3 vector = endCenterOfCapsulePos - startCenterOfCapsulePos; + vector.y = 0f; + vector.Normalize(); + vector *= hSpeed; + vector.y = y; + float num = DistanceXZ(startCenterOfCapsulePos, endCenterOfCapsulePos); + SetCapsulePosition(startCenterOfCapsulePos); + int num2 = Mathf.CeilToInt(num * 1.5f / hSpeed / testTimeStep); + float num3 = float.NegativeInfinity; + Vector3 vector2 = testCharacterController.transform.position; + for (int i = 0; i < num2; i++) + { + Vector3 vector3 = endCenterOfCapsulePos - testCharacterController.transform.position; + if (vector3.sqrMagnitude <= 4f) + { + return num3 - startCenterOfCapsulePos.y; + } + num3 = Mathf.Max(testCharacterController.transform.position.y, num3); + Vector3 vector4 = vector3; + vector4.y = 0f; + vector4.Normalize(); + vector.x = vector4.x * hSpeed; + vector.z = vector4.z * hSpeed; + vector += Physics.gravity * testTimeStep; + testCharacterController.Move(vector * testTimeStep); + Vector3 position = testCharacterController.transform.position; + if (position == vector2) + { + return 0f; + } + vector2 = position; + } + return 0f; + } + } + + private static List _instances = new List(); + + private static ReadOnlyCollection instancesReadOnly = _instances.AsReadOnly(); + + public static readonly float maxConnectionDistance = 15f; + + public List links = new List(); + + [EnumMask(typeof(HullMask))] + public HullMask forbiddenHulls; + + [EnumMask(typeof(NodeFlags))] + public NodeFlags flags; + + [Tooltip("The name of the nodegraph gate associated with this node. If the named gate is closed this node will be treated as though it does not exist.")] + public string gateName = ""; + + public static ReadOnlyCollection instances => instancesReadOnly; + + public void OnEnable() + { + _instances.Add(this); + } + + public void OnDisable() + { + _instances.Remove(this); + } + + private void AddLink(MapNode nodeB, float distanceScore, float minJumpHeight, HullClassification hullClassification) + { + int num = links.FindIndex((Link item) => item.nodeB == nodeB); + if (num == -1) + { + links.Add(new Link + { + nodeB = nodeB + }); + num = links.Count - 1; + } + Link value = links[num]; + value.distanceScore = Mathf.Max(value.distanceScore, distanceScore); + value.minJumpHeight = Mathf.Max(value.minJumpHeight, minJumpHeight); + value.hullMask |= 1 << (int)hullClassification; + if (minJumpHeight > 0f) + { + value.jumpHullMask |= 1 << (int)hullClassification; + } + if (string.IsNullOrEmpty(value.gateName)) + { + value.gateName = nodeB.gateName; + } + links[num] = value; + } + + private void BuildGroundLinks(ReadOnlyCollection nodes, MoveProbe moveProbe) + { + Vector3 position = base.transform.position; + for (int i = 0; i < nodes.Count; i++) + { + MapNode mapNode = nodes[i]; + if (mapNode == this) + { + continue; + } + Vector3 position2 = mapNode.transform.position; + float num = maxConnectionDistance; + float num2 = num * num; + float sqrMagnitude = (position2 - position).sqrMagnitude; + if (!(sqrMagnitude < num2)) + { + continue; + } + float distanceScore = Mathf.Sqrt(sqrMagnitude); + for (int j = 0; j < 3; j++) + { + moveProbe.SetHull((HullClassification)j); + if (((uint)forbiddenHulls & (uint)(1 << j)) != 0 || ((uint)mapNode.forbiddenHulls & (uint)(1 << j)) != 0) + { + continue; + } + Vector3 vector = Vector3.up * (moveProbe.testCharacterController.height * 0.5f); + Vector3 vector2 = Vector3.up * 0.01f; + Vector3 vector3 = moveProbe.GetGroundPosition(position) + vector2; + Vector3 vector4 = moveProbe.GetGroundPosition(position2) + vector2; + Vector3 vector5 = vector3 + vector; + Vector3 vector6 = vector4 + vector; + if (moveProbe.CapsuleOverlapTest(vector5) && moveProbe.CapsuleOverlapTest(vector6)) + { + bool num3 = moveProbe.GroundTest(vector5, vector6, 6f); + float num4 = ((!num3) ? moveProbe.JumpTest(vector5, vector6, 7.5f) : 0f); + if (num3 || (num4 > 0f && num4 < 10f)) + { + AddLink(mapNode, distanceScore, num4, (HullClassification)j); + } + } + } + } + } + + private void BuildAirLinks(ReadOnlyCollection nodes, MoveProbe moveProbe) + { + Vector3 position = base.transform.position; + for (int i = 0; i < nodes.Count; i++) + { + MapNode mapNode = nodes[i]; + if (mapNode == this) + { + continue; + } + Vector3 position2 = mapNode.transform.position; + float num = maxConnectionDistance * 2f; + float num2 = num * num; + float sqrMagnitude = (position2 - position).sqrMagnitude; + if (!(sqrMagnitude < num2)) + { + continue; + } + float distanceScore = Mathf.Sqrt(sqrMagnitude); + for (int j = 0; j < 3; j++) + { + if (((uint)forbiddenHulls & (uint)(1 << j)) == 0 && ((uint)mapNode.forbiddenHulls & (uint)(1 << j)) == 0) + { + moveProbe.SetHull((HullClassification)j); + Vector3 vector = position; + Vector3 vector2 = position2; + if (moveProbe.CapsuleOverlapTest(vector) && moveProbe.CapsuleOverlapTest(vector2) && moveProbe.FlyTest(vector, vector2, 6f)) + { + AddLink(mapNode, distanceScore, 0f, (HullClassification)j); + } + } + } + } + } + + private void BuildRailLinks(ReadOnlyCollection nodes, MoveProbe moveProbe) + { + Vector3 position = base.transform.position; + for (int i = 0; i < nodes.Count; i++) + { + MapNode mapNode = nodes[i]; + if (mapNode == this) + { + continue; + } + Vector3 position2 = mapNode.transform.position; + float num = maxConnectionDistance * 2f; + float num2 = num * num; + float sqrMagnitude = (position2 - position).sqrMagnitude; + if (!(sqrMagnitude < num2)) + { + continue; + } + float distanceScore = Mathf.Sqrt(sqrMagnitude); + for (int j = 0; j < 3; j++) + { + HullDef hullDef = HullDef.Find((HullClassification)j); + if (((uint)forbiddenHulls & (uint)(1 << j)) != 0 || ((uint)mapNode.forbiddenHulls & (uint)(1 << j)) != 0) + { + continue; + } + moveProbe.SetHull((HullClassification)j); + Vector3 vector = position; + Vector3 vector2 = position2; + if (!(Vector3.Angle(Vector3.up, vector2 - vector) <= 50f)) + { + vector.y += hullDef.height; + vector2.y += hullDef.height; + if (moveProbe.CapsuleOverlapTest(vector) && moveProbe.CapsuleOverlapTest(vector2) && moveProbe.FlyTest(vector, vector2, 6f)) + { + AddLink(mapNode, distanceScore, 0f, (HullClassification)j); + } + } + } + } + } + + public void BuildLinks(ReadOnlyCollection nodes, MapNodeGroup.GraphType graphType) + { + links.Clear(); + Vector3 position = base.transform.position; + MoveProbe moveProbe = new MoveProbe(); + moveProbe.Init(); + switch (graphType) + { + case MapNodeGroup.GraphType.Ground: + BuildGroundLinks(nodes, moveProbe); + break; + case MapNodeGroup.GraphType.Air: + BuildAirLinks(nodes, moveProbe); + break; + case MapNodeGroup.GraphType.Rail: + BuildRailLinks(nodes, moveProbe); + break; + } + MapNodeLink[] components = GetComponents(); + foreach (MapNodeLink mapNodeLink in components) + { + if (!mapNodeLink.other) + { + continue; + } + Link link = default(Link); + link.nodeB = mapNodeLink.other; + link.distanceScore = Vector3.Distance(position, mapNodeLink.other.transform.position); + link.minJumpHeight = mapNodeLink.minJumpHeight; + link.gateName = mapNodeLink.gateName; + link.hullMask = -1; + Link link2 = link; + bool flag = false; + for (int j = 0; j < links.Count; j++) + { + if (links[j].nodeB == mapNodeLink.other) + { + links[j] = link2; + flag = true; + break; + } + } + if (!flag) + { + links.Add(link2); + } + } + moveProbe.Destroy(); + } + + public bool TestLineOfSight(MapNode other) + { + return !Physics.Linecast(base.transform.position + Vector3.up, other.transform.position + Vector3.up, LayerIndex.world.mask); + } + + public bool TestNoCeiling() + { + return !Physics.Raycast(new Ray(base.transform.position, Vector3.up), float.PositiveInfinity, LayerIndex.world.mask, QueryTriggerInteraction.Ignore); + } + + public bool TestTeleporterOK() + { + float num = 15f; + int num2 = 20; + float num3 = 7f; + float num4 = 3f; + float num5 = 360f / (float)num2; + for (int i = 0; i < num2; i++) + { + Vector3 vector = Quaternion.AngleAxis(num5 * (float)i, Vector3.up) * (Vector3.forward * num); + Vector3 origin = base.transform.position + vector + Vector3.up * num3; + if (!Physics.Raycast(new Ray(origin, Vector3.down), out var _, num4 + num3, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + return false; + } + } + Debug.DrawRay(base.transform.position, base.transform.up * 20f, Color.green, 15f); + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNodeGroup.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNodeGroup.cs new file mode 100644 index 0000000..0ec891a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNodeGroup.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using UnityEngine; + +namespace RoR2.Navigation; + +public class MapNodeGroup : MonoBehaviour +{ + public enum GraphType + { + Ground, + Air, + Rail + } + + public NodeGraph nodeGraph; + + public Transform testPointA; + + public Transform testPointB; + + public HullClassification debugHullDef; + + public GraphType graphType; + + public void Clear() + { + for (int num = base.transform.childCount - 1; num >= 0; num--) + { + Object.DestroyImmediate(base.transform.GetChild(num).gameObject); + } + } + + public GameObject AddNode(Vector3 position) + { + GameObject obj = new GameObject(); + obj.transform.position = position; + obj.transform.parent = base.transform; + obj.AddComponent(); + obj.name = "MapNode"; + return obj; + } + + public List GetNodes() + { + List result = new List(); + GetComponentsInChildren(includeInactive: false, result); + return result; + } + + public void UpdateNoCeilingMasks() + { + int num = 0; + foreach (MapNode node in GetNodes()) + { + node.flags &= ~NodeFlags.NoCeiling; + if (node.TestNoCeiling()) + { + num++; + node.flags |= NodeFlags.NoCeiling; + } + } + Debug.LogFormat("{0} successful ceiling masks baked.", num); + } + + public void UpdateTeleporterMasks() + { + int num = 0; + foreach (MapNode node in GetNodes()) + { + node.flags &= ~NodeFlags.TeleporterOK; + if (node.TestTeleporterOK()) + { + num++; + node.flags |= NodeFlags.TeleporterOK; + } + } + Debug.LogFormat("{0} successful teleporter masks baked.", num); + } + + public void Bake(NodeGraph nodeGraph) + { + List nodes = GetNodes(); + ReadOnlyCollection readOnlyCollection = nodes.AsReadOnly(); + for (int i = 0; i < nodes.Count; i++) + { + nodes[i].BuildLinks(readOnlyCollection, graphType); + } + List list = new List(); + for (int j = 0; j < nodes.Count; j++) + { + MapNode mapNode = nodes[j]; + SerializableBitArray serializableBitArray = new SerializableBitArray(nodes.Count); + for (int k = 0; k < nodes.Count; k++) + { + MapNode other = nodes[k]; + serializableBitArray[k] = mapNode.TestLineOfSight(other); + } + list.Add(serializableBitArray); + } + nodeGraph.SetNodes(readOnlyCollection, list.AsReadOnly()); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNodeLink.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNodeLink.cs new file mode 100644 index 0000000..6e6d073 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/MapNodeLink.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +namespace RoR2.Navigation; + +[RequireComponent(typeof(MapNode))] +public class MapNodeLink : MonoBehaviour +{ + public MapNode other; + + public float minJumpHeight; + + [Tooltip("The gate name associated with this link. If the named gate is closed, this link will not be used in pathfinding.")] + public string gateName = ""; + + public GameObject[] objectsToEnableDuringTest; + + public GameObject[] objectsToDisableDuringTest; + + private void OnValidate() + { + if (other == this) + { + Debug.LogWarning("Map node link cannot link a node to itself."); + other = null; + } + if ((bool)other && other.GetComponentInParent() != GetComponentInParent()) + { + Debug.LogWarning("Map node link cannot link to a node in a separate node group."); + other = null; + } + } + + private void OnDrawGizmos() + { + if ((bool)other) + { + Vector3 position = base.transform.position; + Vector3 position2 = other.transform.position; + Vector3 vector = (position + position2) * 0.5f; + Color yellow = Color.yellow; + yellow.a = 0.5f; + Gizmos.color = Color.yellow; + Gizmos.DrawLine(position, vector); + Gizmos.color = yellow; + Gizmos.DrawLine(vector, position2); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeFlags.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeFlags.cs new file mode 100644 index 0000000..72a126d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeFlags.cs @@ -0,0 +1,14 @@ +using System; + +namespace RoR2.Navigation; + +[Flags] +public enum NodeFlags : byte +{ + None = 0, + NoCeiling = 1, + TeleporterOK = 2, + NoCharacterSpawn = 4, + NoChestSpawn = 8, + NoShrineSpawn = 0x10 +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraph.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraph.cs new file mode 100644 index 0000000..b9c9c56 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraph.cs @@ -0,0 +1,1161 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; +using HG; +using Unity.Collections; +using UnityEngine; + +namespace RoR2.Navigation; + +[CreateAssetMenu(menuName = "RoR2/NodeGraph")] +[PreferBinarySerialization] +public class NodeGraph : ScriptableObject +{ + [Serializable] + public struct NodeIndex : IEquatable + { + public int nodeIndex; + + public static readonly NodeIndex invalid = new NodeIndex(-1); + + public NodeIndex(int nodeIndex) + { + this.nodeIndex = nodeIndex; + } + + public static bool operator ==(NodeIndex lhs, NodeIndex rhs) + { + return lhs.nodeIndex == rhs.nodeIndex; + } + + public static bool operator !=(NodeIndex lhs, NodeIndex rhs) + { + return lhs.nodeIndex != rhs.nodeIndex; + } + + public override bool Equals(object other) + { + if (other is NodeIndex) + { + return ((NodeIndex)other).nodeIndex == nodeIndex; + } + return false; + } + + public override int GetHashCode() + { + return nodeIndex; + } + + public bool Equals(NodeIndex other) + { + return nodeIndex == other.nodeIndex; + } + } + + [Serializable] + public struct LinkIndex + { + public int linkIndex; + + public static readonly LinkIndex invalid = new LinkIndex + { + linkIndex = -1 + }; + + public static bool operator ==(LinkIndex lhs, LinkIndex rhs) + { + return lhs.linkIndex == rhs.linkIndex; + } + + public static bool operator !=(LinkIndex lhs, LinkIndex rhs) + { + return lhs.linkIndex != rhs.linkIndex; + } + + public override bool Equals(object other) + { + if (other is LinkIndex) + { + return ((LinkIndex)other).linkIndex == linkIndex; + } + return false; + } + + public override int GetHashCode() + { + return linkIndex; + } + } + + [Serializable] + public struct LinkListIndex + { + public int index; + + public uint size; + } + + [Serializable] + public struct Node + { + public Vector3 position; + + public LinkListIndex linkListIndex; + + public HullMask forbiddenHulls; + + public SerializableBitArray lineOfSightMask; + + public byte gateIndex; + + public NodeFlags flags; + } + + [Serializable] + public struct Link + { + public NodeIndex nodeIndexA; + + public NodeIndex nodeIndexB; + + public float distanceScore; + + public float maxSlope; + + public float minJumpHeight; + + public int hullMask; + + public int jumpHullMask; + + public byte gateIndex; + } + + private struct NodePositionGetter : IPosition3Getter + { + private readonly NodeGraph nodeGraph; + + public NodePositionGetter(NodeGraph nodeGraph) + { + this.nodeGraph = nodeGraph; + } + + public Vector3 GetPosition3(NodeIndex item) + { + return nodeGraph.nodes[item.nodeIndex].position; + } + } + + public readonly struct PathRequestPosition + { + public readonly NodeIndex? nodeIndex; + + public readonly Vector3? position; + + private PathRequestPosition(NodeIndex nodeIndex) + { + this.nodeIndex = nodeIndex; + position = null; + } + + private PathRequestPosition(Vector3 position) + { + nodeIndex = null; + this.position = position; + } + + public static implicit operator PathRequestPosition(NodeIndex nodeIndex) + { + return new PathRequestPosition(nodeIndex); + } + + public static implicit operator PathRequestPosition(Vector3 position) + { + return new PathRequestPosition(position); + } + } + + public class PathRequest + { + public Path path; + + public PathRequestPosition startPos; + + public PathRequestPosition endPos; + + public HullClassification hullClassification; + + public float maxSlope; + + public float maxJumpHeight; + + public float maxSpeed; + + public PathRequest() + { + Init(); + } + + public void Reset() + { + Init(); + } + + private void Init() + { + path = null; + startPos = NodeIndex.invalid; + endPos = NodeIndex.invalid; + hullClassification = HullClassification.Human; + maxSlope = 0f; + maxJumpHeight = 0f; + maxSpeed = 0f; + } + } + + private static class NodeFilters + { + public interface INodeCheckFilterComponent + { + bool CheckNode(NodeGraph nodeGraph, ref Node node); + } + + public struct NodeCheckFilterAnd : INodeCheckFilterComponent where TFilterA : INodeCheckFilterComponent where TFilterB : INodeCheckFilterComponent + { + private TFilterA filterA; + + private TFilterB filterB; + + public NodeCheckFilterAnd(TFilterA filterA, TFilterB filterB) + { + this.filterA = filterA; + this.filterB = filterB; + } + + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + if (filterA.CheckNode(nodeGraph, ref node)) + { + return filterB.CheckNode(nodeGraph, ref node); + } + return false; + } + } + + public struct NodeSearchFilter : IBlockMapSearchFilter where TNodeCheckFilter : INodeCheckFilterComponent + { + private readonly NodeGraph nodeGraph; + + private TNodeCheckFilter nodeCheckFilter; + + public NodeSearchFilter(NodeGraph nodeGraph, TNodeCheckFilter nodeCheckFilter) + { + this.nodeGraph = nodeGraph; + this.nodeCheckFilter = nodeCheckFilter; + } + + public bool CheckItem(NodeIndex item, ref bool shouldFinish) + { + return nodeCheckFilter.CheckNode(nodeGraph, ref nodeGraph.nodes[item.nodeIndex]); + } + } + + public readonly struct NodeHullFilter : INodeCheckFilterComponent + { + private readonly HullMask hullMask; + + public NodeHullFilter(HullMask hullMask) + { + this.hullMask = hullMask; + } + + public NodeHullFilter(HullClassification hullClassification) + { + hullMask = (HullMask)(1 << (int)hullClassification); + } + + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + return (node.forbiddenHulls & hullMask) == 0; + } + } + + public readonly struct NodeFlagsFilter : INodeCheckFilterComponent + { + private readonly NodeFlags requiredFlags; + + private readonly NodeFlags forbiddenFlags; + + public NodeFlagsFilter(NodeFlags requiredFlags, NodeFlags forbiddenFlags) + { + this.requiredFlags = requiredFlags; + this.forbiddenFlags = forbiddenFlags; + } + + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + NodeFlags flags = node.flags; + if ((flags & forbiddenFlags) == 0) + { + return (flags & requiredFlags) == requiredFlags; + } + return false; + } + } + + [StructLayout(LayoutKind.Sequential, Size = 1)] + public readonly struct NodeAvailableFilter : INodeCheckFilterComponent + { + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + if (node.gateIndex != 0) + { + return nodeGraph.openGates[node.gateIndex]; + } + return true; + } + } + + public struct NodeMinDistanceFilter : INodeCheckFilterComponent + { + private readonly Vector3 position; + + private readonly float minDistanceSqr; + + public NodeMinDistanceFilter(Vector3 position, float minDistance) + { + this.position = position; + minDistanceSqr = minDistance * minDistance; + } + + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + return (node.position - position).sqrMagnitude >= minDistanceSqr; + } + } + + public struct NodeRaycastFilter : INodeCheckFilterComponent + { + private readonly Vector3 raycastOrigin; + + private readonly Vector3 raycastOffset; + + private readonly int maxRaycasts; + + private int raycastsPerformed; + + public NodeRaycastFilter(Vector3 raycastOrigin, Vector3 raycastOffset, int maxRaycasts) + { + this.raycastOrigin = raycastOrigin + raycastOffset; + this.raycastOffset = raycastOffset; + this.maxRaycasts = maxRaycasts; + raycastsPerformed = 0; + } + + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + if (raycastsPerformed < maxRaycasts) + { + raycastsPerformed++; + if (Physics.Linecast(raycastOrigin, node.position + raycastOffset, out var _, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) + { + return false; + } + } + return true; + } + } + + public struct NodeOverheadFilter : INodeCheckFilterComponent + { + private Vector3 position; + + private bool enabled; + + public NodeOverheadFilter(Vector3 position, bool enabled) + { + this.position = position; + this.enabled = enabled; + } + + public bool CheckNode(NodeGraph nodeGraph, ref Node node) + { + if (enabled && Vector3.Dot((node.position - position).normalized, Vector3.up) > 0.70710677f) + { + return false; + } + return true; + } + } + + public static NodeSearchFilter Create(NodeGraph nodeGraph, TFilter nodeCheckFilter) where TFilter : INodeCheckFilterComponent + { + return new NodeSearchFilter(nodeGraph, nodeCheckFilter); + } + + public static NodeCheckFilterAnd And(TFilterA filterA, TFilterB filterB) where TFilterA : INodeCheckFilterComponent where TFilterB : INodeCheckFilterComponent + { + return new NodeCheckFilterAnd(filterA, filterB); + } + + public static NodeCheckFilterAnd> And(TFilterA filterA, TFilterB filterB, TFilterC filterC) where TFilterA : INodeCheckFilterComponent where TFilterB : INodeCheckFilterComponent where TFilterC : INodeCheckFilterComponent + { + return And(filterA, And(filterB, filterC)); + } + + public static NodeCheckFilterAnd>> And(TFilterA filterA, TFilterB filterB, TFilterC filterC, TFilterD filterD) where TFilterA : INodeCheckFilterComponent where TFilterB : INodeCheckFilterComponent where TFilterC : INodeCheckFilterComponent where TFilterD : INodeCheckFilterComponent + { + return And(filterA, And(filterB, filterC, filterD)); + } + + public static NodeCheckFilterAnd>>> And(TFilterA filterA, TFilterB filterB, TFilterC filterC, TFilterD filterD, TFilterE filterE) where TFilterA : INodeCheckFilterComponent where TFilterB : INodeCheckFilterComponent where TFilterC : INodeCheckFilterComponent where TFilterD : INodeCheckFilterComponent where TFilterE : INodeCheckFilterComponent + { + return And(filterA, And(filterB, filterC, filterD, filterE)); + } + } + + [SerializeField] + private Node[] nodes = Array.Empty(); + + [SerializeField] + private Link[] links = Array.Empty(); + + [SerializeField] + private List gateNames = new List { "" }; + + private bool[] openGates = new bool[256]; + + public Vector3 cellSize = new Vector3(15f, 30f, 15f); + + private BlockMap blockMap = new BlockMap(); + + private FixedSizeArrayPool boolPerNodePool = new FixedSizeArrayPool(0); + + private FixedSizeArrayPool floatPerNodePool = new FixedSizeArrayPool(0); + + private FixedSizeArrayPool nodePerNodePool = new FixedSizeArrayPool(0); + + private FixedSizeArrayPool linkPerNodePool = new FixedSizeArrayPool(0); + + private const float overheadDotLimit = 0.70710677f; + + private void OnNodeCountChanged() + { + boolPerNodePool.lengthOfArrays = nodes.Length; + floatPerNodePool.lengthOfArrays = nodes.Length; + nodePerNodePool.lengthOfArrays = nodes.Length; + linkPerNodePool.lengthOfArrays = nodes.Length; + } + + private void Awake() + { + OnNodeCountChanged(); + RebuildBlockMap(); + } + + private void RebuildBlockMap() + { + NativeArray nativeArray = new NativeArray(nodes.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + for (int i = 0; i < nodes.Length; i++) + { + nativeArray[i] = new NodeIndex(i); + } + try + { + blockMap.SetCellSize(cellSize); + blockMap.Set(new NativeArrayIListWrapper(nativeArray), nativeArray.Length, new NodePositionGetter(this)); + } + finally + { + nativeArray.Dispose(); + } + } + + public void Clear() + { + nodes = Array.Empty(); + links = Array.Empty(); + gateNames.Clear(); + gateNames.Add(""); + blockMap.Reset(); + OnNodeCountChanged(); + } + + public void SetNodes(ReadOnlyCollection mapNodes, ReadOnlyCollection lineOfSightMasks) + { + Clear(); + Dictionary dictionary = new Dictionary(); + List list = new List(); + List list2 = new List(); + for (int i = 0; i < mapNodes.Count; i++) + { + MapNode key = mapNodes[i]; + dictionary[key] = new NodeIndex(i); + } + for (int j = 0; j < mapNodes.Count; j++) + { + MapNode mapNode = mapNodes[j]; + NodeIndex nodeIndexA = dictionary[mapNode]; + int count = list2.Count; + for (int k = 0; k < mapNode.links.Count; k++) + { + MapNode.Link link = mapNode.links[k]; + if (!dictionary.ContainsKey(link.nodeB)) + { + Debug.LogErrorFormat(link.nodeB, "[{0}] Node {1} was not registered.", k, link.nodeB); + } + list2.Add(new Link + { + nodeIndexA = nodeIndexA, + nodeIndexB = dictionary[link.nodeB], + distanceScore = link.distanceScore, + minJumpHeight = link.minJumpHeight, + hullMask = link.hullMask, + jumpHullMask = link.jumpHullMask, + gateIndex = RegisterGateName(link.gateName) + }); + } + HullMask hullMask = mapNode.forbiddenHulls; + for (HullClassification hullClassification = HullClassification.Human; hullClassification < HullClassification.Count; hullClassification++) + { + bool flag = false; + int num = 1 << (int)hullClassification; + List list3 = mapNode.links; + for (int l = 0; l < list3.Count; l++) + { + if ((list3[l].hullMask & num) != 0) + { + flag = true; + break; + } + } + if (!flag) + { + hullMask = (HullMask)((int)hullMask | num); + } + } + list.Add(new Node + { + position = mapNode.transform.position, + linkListIndex = new LinkListIndex + { + index = count, + size = (uint)mapNode.links.Count + }, + forbiddenHulls = hullMask, + flags = mapNode.flags, + lineOfSightMask = new SerializableBitArray(lineOfSightMasks[j]), + gateIndex = RegisterGateName(mapNode.gateName) + }); + } + nodes = list.ToArray(); + links = list2.ToArray(); + OnNodeCountChanged(); + RebuildBlockMap(); + } + + public Vector3 GetQuadraticCoordinates(float t, Vector3 startPos, Vector3 apexPos, Vector3 endPos) + { + return Mathf.Pow(1f - t, 2f) * startPos + 2f * t * (1f - t) * apexPos + Mathf.Pow(t, 2f) * endPos; + } + + public Mesh GenerateLinkDebugMesh(HullMask hullMask) + { + using WireMeshBuilder wireMeshBuilder = new WireMeshBuilder(); + Link[] array = links; + for (int i = 0; i < array.Length; i++) + { + Link link = array[i]; + if (((uint)link.hullMask & (uint)hullMask) == 0) + { + continue; + } + Vector3 position = nodes[link.nodeIndexA.nodeIndex].position; + Vector3 position2 = nodes[link.nodeIndexB.nodeIndex].position; + Vector3 vector = (position + position2) * 0.5f; + bool num = ((uint)link.jumpHullMask & (uint)hullMask) != 0; + Color color = (num ? Color.cyan : Color.green); + if (num) + { + Vector3 apexPos = vector; + apexPos.y = position.y + link.minJumpHeight; + int num2 = 8; + Vector3 p = position; + for (int j = 1; j <= num2; j++) + { + if (j > num2 / 2) + { + color.a = 0.1f; + } + Vector3 quadraticCoordinates = GetQuadraticCoordinates((float)j / (float)num2, position, apexPos, position2); + wireMeshBuilder.AddLine(p, color, quadraticCoordinates, color); + p = quadraticCoordinates; + } + } + else + { + Color c = color; + c.a = 0.1f; + wireMeshBuilder.AddLine(position, color, (position + position2) * 0.5f, c); + } + } + return wireMeshBuilder.GenerateMesh(); + } + + public void DebugDrawLinks(HullClassification hull) + { + int num = 1 << (int)hull; + Link[] array = links; + for (int i = 0; i < array.Length; i++) + { + Link link = array[i]; + if ((link.hullMask & num) == 0) + { + continue; + } + Vector3 position = nodes[link.nodeIndexA.nodeIndex].position; + Vector3 position2 = nodes[link.nodeIndexB.nodeIndex].position; + Vector3 vector = (position + position2) * 0.5f; + bool num2 = (link.jumpHullMask & num) != 0; + Color color = (num2 ? Color.cyan : Color.green); + if (num2) + { + Vector3 apexPos = vector; + apexPos.y = position.y + link.minJumpHeight; + int num3 = 8; + Vector3 start = position; + for (int j = 1; j <= num3; j++) + { + if (j > num3 / 2) + { + color.a = 0.1f; + } + Vector3 quadraticCoordinates = GetQuadraticCoordinates((float)j / (float)num3, position, apexPos, position2); + Debug.DrawLine(start, quadraticCoordinates, color, 10f); + start = quadraticCoordinates; + } + } + else + { + Debug.DrawLine(position, vector, color, 10f, depthTest: false); + Color color2 = color; + color2.a = 0.1f; + Debug.DrawLine(vector, position2, color2, 10f, depthTest: false); + } + } + } + + public void DebugDrawPath(Vector3 startPos, Vector3 endPos) + { + Path path = new Path(this); + ComputePath(new PathRequest + { + startPos = startPos, + endPos = endPos, + path = path, + hullClassification = HullClassification.Human + }).Wait(); + if (path.status == PathStatus.Valid) + { + for (int i = 1; i < path.waypointsCount; i++) + { + Debug.DrawLine(nodes[path[i - 1].nodeIndex.nodeIndex].position, nodes[path[i].nodeIndex.nodeIndex].position, Color.red, 10f); + } + } + } + + public void DebugHighlightNodesWithNoLinks() + { + Node[] array = nodes; + for (int i = 0; i < array.Length; i++) + { + Node node = array[i]; + if (node.linkListIndex.size == 0) + { + Debug.DrawRay(node.position, Vector3.up * 100f, Color.cyan, 60f); + } + } + } + + public int GetNodeCount() + { + return nodes.Length; + } + + public List GetActiveNodesForHullMask(HullMask hullMask) + { + List list = new List(nodes.Length); + GetActiveNodesForHullMask(hullMask, list); + return list; + } + + public void GetActiveNodesForHullMask(HullMask hullMask, List dest) + { + dest.Capacity = Math.Max(dest.Capacity, nodes.Length); + for (int i = 0; i < nodes.Length; i++) + { + if ((nodes[i].forbiddenHulls & hullMask) == 0 && (nodes[i].gateIndex == 0 || openGates[nodes[i].gateIndex])) + { + dest.Add(new NodeIndex(i)); + } + } + } + + public List GetActiveNodesForHullMaskWithFlagConditions(HullMask hullMask, NodeFlags requiredFlags, NodeFlags forbiddenFlags) + { + List list = new List(nodes.Length); + GetActiveNodesForHullMaskWithFlagConditions(hullMask, requiredFlags, forbiddenFlags, list); + return list; + } + + public void GetActiveNodesForHullMaskWithFlagConditions(HullMask hullMask, NodeFlags requiredFlags, NodeFlags forbiddenFlags, List dest) + { + for (int i = 0; i < nodes.Length; i++) + { + NodeFlags flags = nodes[i].flags; + if ((flags & forbiddenFlags) == 0 && (flags & requiredFlags) == requiredFlags && (nodes[i].forbiddenHulls & hullMask) == 0 && (nodes[i].gateIndex == 0 || openGates[nodes[i].gateIndex])) + { + dest.Add(new NodeIndex(i)); + } + } + } + + public List FindNodesInRange(Vector3 position, float minRange, float maxRange, HullMask hullMask) + { + List list = new List(); + FindNodesInRange(position, minRange, maxRange, hullMask, list); + return list; + } + + public void FindNodesInRange(Vector3 position, float minRange, float maxRange, HullMask hullMask, List dest) + { + NodeFilters.NodeSearchFilter>> filter = NodeFilters.Create(this, NodeFilters.And(new NodeFilters.NodeHullFilter(hullMask), default(NodeFilters.NodeAvailableFilter), new NodeFilters.NodeMinDistanceFilter(position, minRange))); + blockMap.GetNearestItemsWhichPassFilter(position, maxRange, ref filter, dest); + } + + public List FindNodesInRangeWithFlagConditions(Vector3 position, float minRange, float maxRange, HullMask hullMask, NodeFlags requiredFlags, NodeFlags forbiddenFlags, bool preventOverhead) + { + List list = new List(); + FindNodesInRangeWithFlagConditions(position, minRange, maxRange, hullMask, requiredFlags, forbiddenFlags, preventOverhead, list); + return list; + } + + public void FindNodesInRangeWithFlagConditions(Vector3 position, float minRange, float maxRange, HullMask hullMask, NodeFlags requiredFlags, NodeFlags forbiddenFlags, bool preventOverhead, List dest) + { + NodeFilters.NodeSearchFilter>>>> filter = NodeFilters.Create(this, NodeFilters.And(new NodeFilters.NodeFlagsFilter(requiredFlags, forbiddenFlags), new NodeFilters.NodeHullFilter(hullMask), default(NodeFilters.NodeAvailableFilter), new NodeFilters.NodeOverheadFilter(position, preventOverhead), new NodeFilters.NodeMinDistanceFilter(position, minRange))); + blockMap.GetNearestItemsWhichPassFilter(position, maxRange, ref filter, dest); + } + + public bool GetNodePosition(NodeIndex nodeIndex, out Vector3 position) + { + if (nodeIndex != NodeIndex.invalid && nodeIndex.nodeIndex < nodes.Length) + { + position = nodes[nodeIndex.nodeIndex].position; + return true; + } + position = Vector3.zero; + return false; + } + + public bool GetNodeFlags(NodeIndex nodeIndex, out NodeFlags flags) + { + if (nodeIndex != NodeIndex.invalid && nodeIndex.nodeIndex < nodes.Length) + { + flags = nodes[nodeIndex.nodeIndex].flags; + return true; + } + flags = NodeFlags.None; + return false; + } + + public LinkIndex[] GetActiveNodeLinks(NodeIndex nodeIndex) + { + if (nodeIndex != NodeIndex.invalid && nodeIndex.nodeIndex < nodes.Length) + { + LinkListIndex linkListIndex = nodes[nodeIndex.nodeIndex].linkListIndex; + LinkIndex[] array = new LinkIndex[linkListIndex.size]; + int index = linkListIndex.index; + for (int i = 0; i < linkListIndex.size; i++) + { + array[i] = new LinkIndex + { + linkIndex = index++ + }; + } + return array; + } + return null; + } + + public void GetActiveNodeLinks(NodeIndex nodeIndex, List results) + { + if (nodeIndex != NodeIndex.invalid && nodeIndex.nodeIndex < nodes.Length) + { + LinkListIndex linkListIndex = nodes[nodeIndex.nodeIndex].linkListIndex; + int index = linkListIndex.index; + for (int i = 0; i < linkListIndex.size; i++) + { + results.Add(new LinkIndex + { + linkIndex = index++ + }); + } + } + } + + public bool TestNodeLineOfSight(NodeIndex nodeIndexA, NodeIndex nodeIndexB) + { + if (nodeIndexA != NodeIndex.invalid && nodeIndexA.nodeIndex < nodes.Length && nodeIndexB != NodeIndex.invalid && nodeIndexB.nodeIndex < nodes.Length) + { + return nodes[nodeIndexA.nodeIndex].lineOfSightMask[nodeIndexB.nodeIndex]; + } + return false; + } + + public bool GetPositionAlongLink(LinkIndex linkIndex, float t, out Vector3 position) + { + if (linkIndex != LinkIndex.invalid && linkIndex.linkIndex < links.Length) + { + position = Vector3.LerpUnclamped(nodes[links[linkIndex.linkIndex].nodeIndexA.nodeIndex].position, nodes[links[linkIndex.linkIndex].nodeIndexB.nodeIndex].position, t); + return true; + } + position = Vector3.zero; + return false; + } + + public bool IsLinkSuitableForHull(LinkIndex linkIndex, HullClassification hullClassification) + { + if (linkIndex != LinkIndex.invalid && linkIndex.linkIndex < links.Length) + { + if ((links[linkIndex.linkIndex].hullMask & (1 << (int)hullClassification)) != 0) + { + if (links[linkIndex.linkIndex].gateIndex != 0) + { + return openGates[links[linkIndex.linkIndex].gateIndex]; + } + return true; + } + return false; + } + return false; + } + + public bool IsLinkSuitableForHull(LinkIndex linkIndex, HullMask hullMask) + { + if (linkIndex != LinkIndex.invalid && linkIndex.linkIndex < links.Length) + { + if (((uint)links[linkIndex.linkIndex].hullMask & (uint)hullMask) != 0) + { + if (links[linkIndex.linkIndex].gateIndex != 0) + { + return openGates[links[linkIndex.linkIndex].gateIndex]; + } + return true; + } + return false; + } + return false; + } + + public NodeIndex GetLinkStartNode(LinkIndex linkIndex) + { + if (linkIndex != LinkIndex.invalid && linkIndex.linkIndex < links.Length) + { + return links[linkIndex.linkIndex].nodeIndexA; + } + return NodeIndex.invalid; + } + + public NodeIndex GetLinkEndNode(LinkIndex linkIndex) + { + if (linkIndex != LinkIndex.invalid && linkIndex.linkIndex < links.Length) + { + return links[linkIndex.linkIndex].nodeIndexB; + } + return NodeIndex.invalid; + } + + public NodeIndex FindClosestNode(Vector3 position, HullClassification hullClassification, float maxDistance = float.PositiveInfinity) + { + NodeFilters.NodeSearchFilter> filter = NodeFilters.Create(this, NodeFilters.And(new NodeFilters.NodeHullFilter(hullClassification), default(NodeFilters.NodeAvailableFilter))); + if (blockMap.GetNearestItemWhichPassesFilter(position, maxDistance, ref filter, out var dest)) + { + return dest; + } + return NodeIndex.invalid; + } + + public NodeIndex FindClosestNodeWithRaycast(Vector3 position, HullClassification hullClassification, float maxDistance, int maxRaycasts) + { + NodeFilters.NodeSearchFilter>> filter = NodeFilters.Create(this, NodeFilters.And(new NodeFilters.NodeHullFilter(hullClassification), default(NodeFilters.NodeAvailableFilter), new NodeFilters.NodeRaycastFilter(position, new Vector3(0f, 0.2f, 0f), 3))); + if (blockMap.GetNearestItemWhichPassesFilter(position, maxDistance, ref filter, out var dest)) + { + return dest; + } + return NodeIndex.invalid; + } + + public NodeIndex FindClosestNodeWithFlagConditions(Vector3 position, HullClassification hullClassification, NodeFlags requiredFlags, NodeFlags forbiddenFlags, bool preventOverhead) + { + NodeFilters.NodeSearchFilter>>> filter = NodeFilters.Create(this, NodeFilters.And(new NodeFilters.NodeFlagsFilter(requiredFlags, forbiddenFlags), new NodeFilters.NodeHullFilter(hullClassification), default(NodeFilters.NodeAvailableFilter), new NodeFilters.NodeOverheadFilter(position, preventOverhead))); + if (blockMap.GetNearestItemWhichPassesFilter(position, float.PositiveInfinity, ref filter, out var dest)) + { + return dest; + } + return NodeIndex.invalid; + } + + private float HeuristicCostEstimate(Vector3 startPos, Vector3 endPos) + { + return Vector3.Distance(startPos, endPos); + } + + private static float DistanceXZ(Vector3 a, Vector3 b) + { + a.y = 0f; + b.y = 0f; + return Vector3.Distance(a, b); + } + + private static void ArrayRemoveNodeIndex(NodeIndex[] array, NodeIndex value, int count) + { + for (int i = 0; i < count; i++) + { + if (array[i] == value) + { + array[i] = array[count - 1]; + break; + } + } + } + + private static void ArrayRemoveNodeIndexFromCachedPosition(NodeIndex[] array, int arrayIndex, int count) + { + array[arrayIndex] = array[count - 1]; + } + + public PathTask ComputePath(PathRequest pathRequest) + { + bool[] array = boolPerNodePool.Request(); + bool[] array2 = boolPerNodePool.Request(); + NodeIndex[] array3 = nodePerNodePool.Request(); + LinkIndex[] array4 = linkPerNodePool.Request(); + ArrayUtils.SetAll(array4, in LinkIndex.invalid); + float[] array5 = floatPerNodePool.Request(); + float value = float.PositiveInfinity; + ArrayUtils.SetAll(array5, in value); + float[] array6 = floatPerNodePool.Request(); + value = float.PositiveInfinity; + ArrayUtils.SetAll(array6, in value); + try + { + ResolveNodePosition(in pathRequest.startPos, out var dest2, 100f, 2); + ResolveNodePosition(in pathRequest.endPos, out var dest3, 500f, 0); + PathTask pathTask = new PathTask(pathRequest.path); + pathTask.status = PathTask.TaskStatus.Running; + if (dest2.nodeIndex == NodeIndex.invalid.nodeIndex || dest3.nodeIndex == NodeIndex.invalid.nodeIndex) + { + pathRequest.path.Clear(); + pathTask.status = PathTask.TaskStatus.Complete; + pathTask.wasReachable = false; + return pathTask; + } + int num = 1 << (int)pathRequest.hullClassification; + array2[dest2.nodeIndex] = true; + int num2 = 1; + array3[0] = dest2; + array5[dest2.nodeIndex] = 0f; + array6[dest2.nodeIndex] = HeuristicCostEstimate(nodes[dest2.nodeIndex].position, nodes[dest3.nodeIndex].position); + int arrayIndex = -1; + while (num2 > 0) + { + NodeIndex nodeIndex = NodeIndex.invalid; + float num3 = float.PositiveInfinity; + for (int i = 0; i < num2; i++) + { + int nodeIndex2 = array3[i].nodeIndex; + if (array6[nodeIndex2] <= num3) + { + num3 = array6[nodeIndex2]; + nodeIndex = new NodeIndex(nodeIndex2); + arrayIndex = i; + } + } + if (nodeIndex.nodeIndex == dest3.nodeIndex) + { + ReconstructPath(pathRequest.path, array4, array4[nodeIndex.nodeIndex], pathRequest); + pathTask.status = PathTask.TaskStatus.Complete; + pathTask.wasReachable = true; + return pathTask; + } + array2[nodeIndex.nodeIndex] = false; + ArrayRemoveNodeIndexFromCachedPosition(array3, arrayIndex, num2); + num2--; + array[nodeIndex.nodeIndex] = true; + LinkListIndex linkListIndex = nodes[nodeIndex.nodeIndex].linkListIndex; + LinkIndex linkIndex = default(LinkIndex); + linkIndex.linkIndex = linkListIndex.index; + LinkIndex linkIndex2 = linkIndex; + linkIndex = default(LinkIndex); + linkIndex.linkIndex = linkListIndex.index + (int)linkListIndex.size; + for (LinkIndex linkIndex3 = linkIndex; linkIndex2.linkIndex < linkIndex3.linkIndex; linkIndex2.linkIndex++) + { + Link link = links[linkIndex2.linkIndex]; + NodeIndex nodeIndexB = link.nodeIndexB; + if (array[nodeIndexB.nodeIndex]) + { + continue; + } + if ((num & link.jumpHullMask) != 0 && links[linkIndex2.linkIndex].minJumpHeight > 0f) + { + Vector3 position = nodes[link.nodeIndexA.nodeIndex].position; + Vector3 position2 = nodes[link.nodeIndexB.nodeIndex].position; + if (Trajectory.CalculateApex(Trajectory.CalculateInitialYSpeed(Trajectory.CalculateGroundTravelTime(pathRequest.maxSpeed, DistanceXZ(position, position2)), position2.y - position.y)) > pathRequest.maxJumpHeight) + { + continue; + } + } + if ((link.hullMask & num) != 0 && (link.gateIndex == 0 || openGates[link.gateIndex])) + { + float distanceScore = link.distanceScore; + float num4 = array5[nodeIndex.nodeIndex] + distanceScore; + if (!array2[nodeIndexB.nodeIndex]) + { + array2[nodeIndexB.nodeIndex] = true; + array3[num2] = nodeIndexB; + num2++; + } + else if (num4 >= array5[nodeIndexB.nodeIndex]) + { + continue; + } + array4[nodeIndexB.nodeIndex] = linkIndex2; + array5[nodeIndexB.nodeIndex] = num4; + array6[nodeIndexB.nodeIndex] = num4 + HeuristicCostEstimate(nodes[nodeIndexB.nodeIndex].position, nodes[dest3.nodeIndex].position); + } + } + } + pathRequest.path.Clear(); + pathTask.status = PathTask.TaskStatus.Complete; + return pathTask; + } + catch (Exception ex) + { + Debug.LogError($"ComputePath exception: {ex}\n\n{ex.StackTrace}"); + } + finally + { + floatPerNodePool.Return(array6, FixedSizeArrayPool.ClearType.NONE); + floatPerNodePool.Return(array5, FixedSizeArrayPool.ClearType.NONE); + linkPerNodePool.Return(array4, FixedSizeArrayPool.ClearType.NONE); + nodePerNodePool.Return(array3, FixedSizeArrayPool.ClearType.CLEAR); + boolPerNodePool.Return(array2, FixedSizeArrayPool.ClearType.CLEAR); + boolPerNodePool.Return(array, FixedSizeArrayPool.ClearType.CLEAR); + } + return null; + void ResolveNodePosition(in PathRequestPosition pathRequestPosition, out NodeIndex dest, float maxSearchDistance, int maxRaycasts) + { + if (pathRequestPosition.nodeIndex.HasValue) + { + dest = pathRequestPosition.nodeIndex.Value; + } + else if (pathRequestPosition.position.HasValue) + { + dest = FindClosestNodeWithRaycast(pathRequestPosition.position.Value, pathRequest.hullClassification, maxSearchDistance, maxRaycasts); + } + else + { + dest = NodeIndex.invalid; + } + } + } + + private LinkIndex Resolve(LinkIndex[] cameFrom, LinkIndex current) + { + if (current.linkIndex < 0 || current.linkIndex > links.Length) + { + Debug.LogFormat("Link {0} is out of range [0,{1})", current.linkIndex, links.Length); + } + NodeIndex nodeIndexA = links[current.linkIndex].nodeIndexA; + return cameFrom[nodeIndexA.nodeIndex]; + } + + private void ReconstructPath(Path path, LinkIndex[] cameFrom, LinkIndex current, PathRequest pathRequest) + { + int num = 1 << (int)pathRequest.hullClassification; + path.Clear(); + if (current != LinkIndex.invalid) + { + path.PushWaypointToFront(links[current.linkIndex].nodeIndexB, 0f); + } + while (current != LinkIndex.invalid) + { + NodeIndex nodeIndexB = links[current.linkIndex].nodeIndexB; + float minJumpHeight = 0f; + if ((num & links[current.linkIndex].jumpHullMask) != 0 && links[current.linkIndex].minJumpHeight > 0f) + { + Vector3 position = nodes[links[current.linkIndex].nodeIndexA.nodeIndex].position; + Vector3 position2 = nodes[links[current.linkIndex].nodeIndexB.nodeIndex].position; + minJumpHeight = Trajectory.CalculateApex(Trajectory.CalculateInitialYSpeed(Trajectory.CalculateGroundTravelTime(pathRequest.maxSpeed, DistanceXZ(position, position2)), position2.y - position.y)); + } + path.PushWaypointToFront(nodeIndexB, minJumpHeight); + if (cameFrom[links[current.linkIndex].nodeIndexA.nodeIndex] == LinkIndex.invalid) + { + path.PushWaypointToFront(links[current.linkIndex].nodeIndexA, 0f); + } + current = cameFrom[links[current.linkIndex].nodeIndexA.nodeIndex]; + } + path.status = PathStatus.Valid; + } + + private byte RegisterGateName(string gateName) + { + if (string.IsNullOrEmpty(gateName)) + { + return 0; + } + int num = gateNames.IndexOf(gateName); + if (num == -1) + { + num = gateNames.Count; + if (num >= 256) + { + Debug.LogErrorFormat(this, "Nodegraph cannot have more than 255 gate names. Nodegraph={0} gateName={1}", this, gateName); + num = 0; + } + else + { + gateNames.Add(gateName); + } + } + return (byte)num; + } + + public bool IsGateOpen(string gateName) + { + int num = gateNames.IndexOf(gateName); + if (num == -1) + { + return false; + } + return openGates[num]; + } + + public void SetGateState(string gateName, bool open) + { + TrySetGateState(gateName, open); + } + + public bool TrySetGateState(string gateName, bool open) + { + int num = gateNames.IndexOf(gateName); + if (num == -1) + { + return false; + } + openGates[num] = open; + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraphNavigationSystem.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraphNavigationSystem.cs new file mode 100644 index 0000000..0543042 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraphNavigationSystem.cs @@ -0,0 +1,304 @@ +using System; +using HG; +using UnityEngine; + +namespace RoR2.Navigation; + +public class NodeGraphNavigationSystem : BroadNavigationSystem +{ + public struct AgentData + { + public NodeGraph nodeGraph; + + public PathFollower pathFollower; + + public NodeGraph.PathRequest pathRequest; + + public HullClassification hullClassification; + + public PathTask pathTask; + + public float updateInterval; + + public float nextUpdate; + + public bool targetReachable; + + public float lastTargetReachableUpdate; + + public NodeGraph.NodeIndex? lastKnownNode; + + public float timeLastKnownNodeEncountered; + + public float estimatedArrivalTimeAtLastKnownNode; + + private PathFollower.Drawer pathDrawer; + + public bool drawPath + { + get + { + return pathDrawer != null; + } + set + { + if (drawPath != value) + { + if (!value) + { + pathDrawer.Dispose(); + pathDrawer = null; + } + else + { + pathDrawer = new PathFollower.Drawer(pathFollower); + } + } + } + } + + public void Initialize() + { + nextUpdate = float.NegativeInfinity; + nodeGraph = null; + updateInterval = 2f; + hullClassification = HullClassification.Human; + pathFollower = pathFollower ?? new PathFollower(); + pathRequest = pathRequest ?? new NodeGraph.PathRequest(); + targetReachable = false; + lastTargetReachableUpdate = float.NegativeInfinity; + lastKnownNode = null; + timeLastKnownNodeEncountered = float.NegativeInfinity; + estimatedArrivalTimeAtLastKnownNode = float.NegativeInfinity; + drawPath = false; + } + + public void Dispose() + { + drawPath = false; + nodeGraph = null; + nextUpdate = float.NegativeInfinity; + pathFollower.Reset(); + pathRequest.Reset(); + pathTask = null; + } + + public void InvalidatePath() + { + nextUpdate = float.NegativeInfinity; + pathTask = null; + } + } + + public new struct Agent + { + private readonly BroadNavigationSystem.Agent inner; + + private NodeGraphNavigationSystem system => (NodeGraphNavigationSystem)inner.system; + + private ref AgentData agentData => ref system.allAgentData[(int)inner.handle]; + + public NodeGraph nodeGraph + { + get + { + return agentData.nodeGraph; + } + set + { + agentData.nodeGraph = value; + } + } + + public HullClassification hullClassification + { + get + { + return agentData.hullClassification; + } + set + { + agentData.hullClassification = value; + } + } + + public bool drawPath + { + get + { + return agentData.drawPath; + } + set + { + agentData.drawPath = value; + } + } + + public PathFollower pathFollower + { + get + { + return agentData.pathFollower; + } + set + { + agentData.pathFollower = value; + } + } + + public Agent(BroadNavigationSystem.Agent inner) + { + this.inner = inner; + } + + public void InvalidatePath() + { + agentData.InvalidatePath(); + } + + public void DebugDrawPath(Color color, float duration) + { + agentData.pathFollower.DebugDrawPath(color, duration); + } + + public static explicit operator Agent(BroadNavigationSystem.Agent other) + { + return new Agent(other); + } + } + + private AgentData[] allAgentData = Array.Empty(); + + private int maxAgentUpdatesPerFrame = 1; + + private int remainingAgentUpdateBudget; + + public new Agent GetAgent(AgentHandle agentHandle) + { + return new Agent(base.GetAgent(agentHandle)); + } + + protected override void CreateAgent(in AgentHandle index) + { + ArrayUtils.EnsureCapacity(ref allAgentData, base.agentCount); + allAgentData[(int)index].Initialize(); + } + + protected override void DestroyAgent(in AgentHandle index) + { + allAgentData[(int)index].Dispose(); + } + + protected override void UpdateAgents(float deltaTime) + { + remainingAgentUpdateBudget = maxAgentUpdatesPerFrame; + for (AgentHandle agentHandle = (AgentHandle)0; (int)agentHandle < allAgentData.Length; agentHandle++) + { + UpdateAgent(in agentHandle); + } + } + + protected override void ConfigureAgentFromBody(in AgentHandle index, CharacterBody body) + { + ref AgentData reference = ref allAgentData[(int)index]; + if ((bool)body) + { + reference.hullClassification = body.hullClassification; + reference.nodeGraph = (SceneInfo.instance ? SceneInfo.instance.GetNodeGraph(body.isFlying ? MapNodeGroup.GraphType.Air : MapNodeGroup.GraphType.Ground) : null); + } + else + { + reference.hullClassification = HullClassification.Human; + reference.nodeGraph = null; + reference.InvalidatePath(); + } + } + + protected override void InvalidateAgentPath(in AgentHandle index) + { + allAgentData[(int)index].InvalidatePath(); + } + + private void UpdateAgent(in AgentHandle agentHandle) + { + bool flag = false; + ref readonly BaseAgentData agentData = ref GetAgentData(in agentHandle); + if (!agentData.enabled) + { + return; + } + ref AgentData reference = ref allAgentData[(int)agentHandle]; + if (reference.pathTask == null && reference.nextUpdate <= localTime && remainingAgentUpdateBudget != 0) + { + flag = true; + remainingAgentUpdateBudget--; + reference.nextUpdate = localTime + reference.updateInterval; + if (reference.lastKnownNode != reference.pathFollower.nextNode) + { + reference.lastKnownNode = reference.pathFollower.nextNode; + reference.timeLastKnownNodeEncountered = localTime; + Vector3? nextPosition = reference.pathFollower.GetNextPosition(); + if (nextPosition.HasValue && agentData.currentPosition.HasValue && agentData.maxWalkSpeed > 0f) + { + reference.estimatedArrivalTimeAtLastKnownNode = localTime + (nextPosition.Value - agentData.currentPosition.Value).magnitude / agentData.maxWalkSpeed; + } + else + { + reference.estimatedArrivalTimeAtLastKnownNode = float.PositiveInfinity; + } + } + if (agentData.currentPosition.HasValue && agentData.goalPosition.HasValue && (bool)reference.nodeGraph && reference.lastKnownNode.HasValue) + { + reference.pathRequest.startPos = agentData.currentPosition.Value; + if (localTime <= reference.estimatedArrivalTimeAtLastKnownNode + 1f && reference.lastKnownNode.Value.nodeIndex != -1) + { + reference.nodeGraph.GetNodePosition(reference.lastKnownNode.Value, out var position); + float num = (agentData.maxWalkSpeed + reference.updateInterval) * 1.5f; + float num2 = num * num; + if ((position - agentData.currentPosition.Value).sqrMagnitude < num2 && !Physics.Linecast(agentData.currentPosition.Value, position + new Vector3(0f, 0.2f, 0f), out var _, LayerIndex.world.intVal, QueryTriggerInteraction.Ignore)) + { + reference.pathRequest.startPos = reference.lastKnownNode.Value; + } + } + reference.pathRequest.endPos = agentData.goalPosition.Value; + reference.pathRequest.hullClassification = reference.hullClassification; + reference.pathRequest.maxJumpHeight = agentData.maxJumpHeight; + reference.pathRequest.maxSlope = agentData.maxSlopeAngle; + reference.pathRequest.maxSpeed = agentData.maxWalkSpeed; + reference.pathRequest.path = new Path(reference.nodeGraph); + reference.pathTask = reference.nodeGraph.ComputePath(reference.pathRequest); + } + } + if (reference.pathTask != null && (flag || remainingAgentUpdateBudget != 0)) + { + if (!flag) + { + remainingAgentUpdateBudget--; + flag = true; + } + if (reference.pathTask.status == PathTask.TaskStatus.Complete) + { + reference.pathFollower.SetPath(reference.pathTask.path); + reference.lastTargetReachableUpdate = localTime; + reference.targetReachable = reference.pathTask.wasReachable; + reference.pathTask = null; + } + } + if (agentData.currentPosition.HasValue) + { + reference.pathFollower.UpdatePosition(agentData.currentPosition.Value); + } + Vector3? nextPosition2 = reference.pathFollower.GetNextPosition(); + if (reference.targetReachable && !nextPosition2.HasValue) + { + nextPosition2 = agentData.goalPosition; + } + AgentOutput agentOutput = default(AgentOutput); + agentOutput.nextPosition = nextPosition2; + agentOutput.desiredJumpVelocity = (reference.pathFollower.nextWaypointNeedsJump ? reference.pathFollower.CalculateJumpVelocityNeededToReachNextWaypoint(agentData.maxWalkSpeed) : 0f); + agentOutput.targetReachable = reference.targetReachable; + agentOutput.lastPathUpdate = reference.lastTargetReachableUpdate; + AgentOutput output = agentOutput; + SetAgentOutput(in agentHandle, in output); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraphSpider.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraphSpider.cs new file mode 100644 index 0000000..a18377d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/NodeGraphSpider.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using HG; +using JetBrains.Annotations; + +namespace RoR2.Navigation; + +public class NodeGraphSpider +{ + public class StepInfo + { + public NodeGraph.NodeIndex node; + + public StepInfo previousStep; + } + + [NotNull] + private NodeGraph nodeGraph; + + private List uncheckedSteps; + + private BitArray visitedNodes; + + public HullMask hullMask; + + [NotNull] + public List collectedSteps { get; private set; } + + public NodeGraphSpider([NotNull] NodeGraph nodeGraph, HullMask hullMask) + { + if ((object)nodeGraph == null) + { + throw new ArgumentNullException("nodeGraph", "'nodeGraph' must be valid."); + } + this.nodeGraph = nodeGraph; + this.hullMask = hullMask; + collectedSteps = new List(); + uncheckedSteps = new List(); + visitedNodes = new BitArray(nodeGraph.GetNodeCount()); + } + + public bool PerformStep() + { + List list = uncheckedSteps; + uncheckedSteps = new List(); + List list2 = CollectionPool>.RentCollection(); + for (int i = 0; i < list.Count; i++) + { + StepInfo stepInfo = list[i]; + list2.Clear(); + nodeGraph.GetActiveNodeLinks(stepInfo.node, list2); + for (int j = 0; j < list2.Count; j++) + { + NodeGraph.LinkIndex linkIndex = list2[j]; + if (nodeGraph.IsLinkSuitableForHull(linkIndex, hullMask)) + { + NodeGraph.NodeIndex linkEndNode = nodeGraph.GetLinkEndNode(linkIndex); + if (!visitedNodes[linkEndNode.nodeIndex]) + { + uncheckedSteps.Add(new StepInfo + { + node = linkEndNode, + previousStep = stepInfo + }); + visitedNodes[linkEndNode.nodeIndex] = true; + } + } + } + collectedSteps.Add(stepInfo); + } + list2 = CollectionPool>.ReturnCollection(list2); + return list.Count > 0; + } + + public void AddNodeForNextStep(NodeGraph.NodeIndex nodeIndex) + { + if (!(nodeIndex == NodeGraph.NodeIndex.invalid) && !visitedNodes[nodeIndex.nodeIndex]) + { + uncheckedSteps.Add(new StepInfo + { + node = nodeIndex, + previousStep = null + }); + visitedNodes[nodeIndex.nodeIndex] = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Navigation/PathTask.cs b/ilspy_dump/ror2_csproj/RoR2.Navigation/PathTask.cs new file mode 100644 index 0000000..513a389 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Navigation/PathTask.cs @@ -0,0 +1,26 @@ +namespace RoR2.Navigation; + +public class PathTask +{ + public enum TaskStatus + { + NotStarted, + Running, + Complete + } + + public TaskStatus status; + + public bool wasReachable; + + public Path path { get; private set; } + + public PathTask(Path path) + { + this.path = path; + } + + public void Wait() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/AddressPortPair.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/AddressPortPair.cs new file mode 100644 index 0000000..5e0b0ec --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/AddressPortPair.cs @@ -0,0 +1,81 @@ +using System; +using System.Globalization; +using System.Net; + +namespace RoR2.Networking; + +public struct AddressPortPair : IEquatable +{ + public string address; + + public ushort port; + + public bool isValid => !string.IsNullOrEmpty(address); + + public AddressPortPair(string address, ushort port) + { + this.address = address; + this.port = port; + } + + public AddressPortPair(IPAddress address, ushort port) + { + this.address = address.ToString(); + this.port = port; + } + + public static bool TryParse(string str, out AddressPortPair addressPortPair) + { + if (!string.IsNullOrEmpty(str)) + { + int num = str.Length - 1; + while (num >= 0 && str[num] != ':') + { + num--; + } + if (num >= 0) + { + string text = str.Substring(0, num); + string s = str.Substring(num + 1, str.Length - num - 1); + addressPortPair.address = text; + addressPortPair.port = (ushort)(TextSerialization.TryParseInvariant(s, out ushort result) ? result : 0); + return true; + } + } + addressPortPair.address = ""; + addressPortPair.port = 0; + return false; + } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "{0}:{1}", address, port); + } + + public bool Equals(AddressPortPair other) + { + if (string.Equals(address, other.address)) + { + return port == other.port; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is AddressPortPair other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (((address != null) ? address.GetHashCode() : 0) * 397) ^ port.GetHashCode(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/CharacterNetworkTransform.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/CharacterNetworkTransform.cs new file mode 100644 index 0000000..4591621 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/CharacterNetworkTransform.cs @@ -0,0 +1,306 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class CharacterNetworkTransform : NetworkBehaviour +{ + public struct Snapshot + { + public float serverTime; + + public Vector3 position; + + public Vector3 moveVector; + + public Vector3 aimDirection; + + public Quaternion rotation; + + public bool isGrounded; + + public Vector3 groundNormal; + + private static bool LerpGroundNormal(ref Snapshot a, ref Snapshot b, float t, out Vector3 groundNormal) + { + groundNormal = Vector3.zero; + bool num = ((t > 0f) ? b.isGrounded : a.isGrounded); + if (num) + { + if (b.isGrounded) + { + if (a.isGrounded) + { + groundNormal = Vector3.Slerp(a.groundNormal, b.groundNormal, t); + return num; + } + groundNormal = b.groundNormal; + return num; + } + groundNormal = a.groundNormal; + } + return num; + } + + public static Snapshot Lerp(Snapshot a, Snapshot b, float t) + { + Vector3 vector; + bool flag = LerpGroundNormal(ref a, ref b, t, out vector); + Snapshot result = default(Snapshot); + result.position = Vector3.Lerp(a.position, b.position, t); + result.moveVector = Vector3.Lerp(a.moveVector, b.moveVector, t); + result.aimDirection = Vector3.Slerp(a.aimDirection, b.moveVector, t); + result.rotation = Quaternion.Lerp(a.rotation, b.rotation, t); + result.isGrounded = flag; + result.groundNormal = vector; + return result; + } + + public static Snapshot Interpolate(Snapshot a, Snapshot b, float serverTime) + { + float t = (serverTime - a.serverTime) / (b.serverTime - a.serverTime); + Vector3 vector; + bool flag = LerpGroundNormal(ref a, ref b, t, out vector); + Snapshot result = default(Snapshot); + result.serverTime = serverTime; + result.position = Vector3.LerpUnclamped(a.position, b.position, t); + result.moveVector = Vector3.Lerp(a.moveVector, b.moveVector, t); + result.aimDirection = Vector3.Slerp(a.aimDirection, b.aimDirection, t); + result.rotation = Quaternion.Lerp(a.rotation, b.rotation, t); + result.isGrounded = flag; + result.groundNormal = vector; + return result; + } + } + + private static List instancesList = new List(); + + private static ReadOnlyCollection _readOnlyInstancesList = new ReadOnlyCollection(instancesList); + + [Tooltip("The delay in seconds between position network updates.")] + public float positionTransmitInterval = 0.1f; + + [HideInInspector] + public float lastPositionTransmitTime = float.NegativeInfinity; + + [Tooltip("The number of packets of buffers to have.")] + public float interpolationFactor = 2f; + + public Snapshot newestNetSnapshot; + + private List snapshots = new List(); + + public bool debugDuplicatePositions; + + public bool debugSnapshotReceived; + + private bool rigidbodyStartedKinematic = true; + + public static ReadOnlyCollection readOnlyInstancesList => _readOnlyInstancesList; + + public new Transform transform { get; private set; } + + public InputBankTest inputBank { get; private set; } + + public CharacterMotor characterMotor { get; set; } + + public CharacterDirection characterDirection { get; private set; } + + private Rigidbody rigidbody { get; set; } + + public float interpolationDelay => positionTransmitInterval * interpolationFactor; + + public bool hasEffectiveAuthority { get; private set; } + + private Snapshot CalcCurrentSnapshot(float time, float interpolationDelay) + { + float num = time - interpolationDelay; + if (snapshots.Count < 2) + { + Snapshot result = ((snapshots.Count == 0) ? BuildSnapshot() : snapshots[0]); + result.serverTime = num; + return result; + } + int i; + for (i = 0; i < snapshots.Count - 2 && (!(snapshots[i].serverTime <= num) || !(snapshots[i + 1].serverTime >= num)); i++) + { + } + return Snapshot.Interpolate(snapshots[i], snapshots[i + 1], num); + } + + private Snapshot BuildSnapshot() + { + Snapshot result = default(Snapshot); + result.serverTime = PlatformSystems.networkManager.serverFixedTime; + result.position = transform.position; + result.moveVector = (inputBank ? inputBank.moveVector : Vector3.zero); + result.aimDirection = (inputBank ? inputBank.aimDirection : Vector3.zero); + result.rotation = (characterDirection ? Quaternion.Euler(0f, characterDirection.yaw, 0f) : transform.rotation); + result.isGrounded = (bool)characterMotor && characterMotor.isGrounded; + result.groundNormal = (characterMotor ? characterMotor.estimatedGroundNormal : Vector3.zero); + return result; + } + + public void PushSnapshot(Snapshot newSnapshot) + { + if (debugSnapshotReceived) + { + Debug.LogFormat("{0} CharacterNetworkTransform snapshot received.", base.gameObject); + } + if (snapshots.Count > 0) + { + _ = newSnapshot.serverTime; + _ = snapshots[snapshots.Count - 1].serverTime; + } + if (debugDuplicatePositions && snapshots.Count > 0) + { + _ = newSnapshot.position == snapshots[snapshots.Count - 1].position; + } + if (((snapshots.Count > 0) ? snapshots[snapshots.Count - 1].serverTime : float.NegativeInfinity) < newSnapshot.serverTime) + { + snapshots.Add(newSnapshot); + newestNetSnapshot = newSnapshot; + Debug.DrawLine(newSnapshot.position + Vector3.up, newSnapshot.position + Vector3.down, Color.white, 0.25f); + } + float num = PlatformSystems.networkManager.serverFixedTime - interpolationDelay * 2f; + while (snapshots.Count > 2 && snapshots[1].serverTime < num) + { + snapshots.RemoveAt(0); + } + } + + private void Awake() + { + transform = base.transform; + inputBank = GetComponent(); + characterMotor = GetComponent(); + characterDirection = GetComponent(); + rigidbody = GetComponent(); + if ((bool)rigidbody) + { + rigidbodyStartedKinematic = rigidbody.isKinematic; + } + } + + private void Start() + { + newestNetSnapshot = BuildSnapshot(); + UpdateAuthority(); + } + + private void OnEnable() + { + bool num = instancesList.Contains(this); + instancesList.Add(this); + if (num) + { + Debug.LogError("Instance already in list!"); + } + } + + private void OnDisable() + { + instancesList.Remove(this); + if (instancesList.Contains(this)) + { + Debug.LogError("Instance was not fully removed from list!"); + } + } + + private void UpdateAuthority() + { + hasEffectiveAuthority = Util.HasEffectiveAuthority(base.gameObject); + if ((bool)rigidbody) + { + rigidbody.isKinematic = !hasEffectiveAuthority || rigidbodyStartedKinematic; + } + } + + public override void OnStartAuthority() + { + UpdateAuthority(); + } + + public override void OnStopAuthority() + { + UpdateAuthority(); + } + + private void ApplyCurrentSnapshot(float currentTime) + { + Snapshot snapshot = CalcCurrentSnapshot(currentTime, interpolationDelay); + if (!characterMotor) + { + if (rigidbodyStartedKinematic) + { + transform.position = snapshot.position; + } + else + { + rigidbody.MovePosition(snapshot.position); + } + } + if ((bool)inputBank) + { + inputBank.moveVector = snapshot.moveVector; + inputBank.aimDirection = snapshot.aimDirection; + } + if ((bool)characterMotor) + { + characterMotor.netIsGrounded = snapshot.isGrounded; + characterMotor.netGroundNormal = snapshot.groundNormal; + if (characterMotor.Motor.enabled) + { + characterMotor.Motor.MoveCharacter(snapshot.position); + } + else + { + characterMotor.Motor.SetPosition(snapshot.position); + } + } + if ((bool)characterDirection) + { + characterDirection.yaw = snapshot.rotation.eulerAngles.y; + } + else if (rigidbodyStartedKinematic) + { + transform.rotation = snapshot.rotation; + } + else + { + rigidbody.MoveRotation(snapshot.rotation); + } + } + + private void FixedUpdate() + { + if (!hasEffectiveAuthority) + { + ApplyCurrentSnapshot(PlatformSystems.networkManager.serverFixedTime); + } + else + { + newestNetSnapshot = BuildSnapshot(); + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool result = default(bool); + return result; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/CharacterNetworkTransformManager.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/CharacterNetworkTransformManager.cs new file mode 100644 index 0000000..459b86c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/CharacterNetworkTransformManager.cs @@ -0,0 +1,232 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class CharacterNetworkTransformManager : MonoBehaviour +{ + private class CharacterUpdateMessage : MessageBase + { + private static readonly int byteSize = 1; + + private static readonly int floatSize = 4; + + private static readonly int vector3Size = floatSize * 3; + + private static readonly int packedUint32MaxSize = 5; + + private static readonly int gameObjectSize = packedUint32MaxSize; + + private static readonly int packedUnitVector3Size = 2; + + private static readonly int quaternionSize = floatSize * 4; + + public static readonly int maxNetworkSize = byteSize + floatSize + gameObjectSize + vector3Size + packedUnitVector3Size + vector3Size + quaternionSize + packedUnitVector3Size; + + private static readonly byte nonIdentityRotationBit = 2; + + private static readonly byte isGroundedBit = 4; + + public float timestamp; + + public GameObject gameObject; + + public Vector3 newPosition; + + public Vector3 aimDirection; + + public Vector3 moveVector; + + public Quaternion rotation; + + public bool isGrounded; + + public Vector3 groundNormal; + + public override void Serialize(NetworkWriter writer) + { + base.Serialize(writer); + byte b = 0; + bool num = rotation != Quaternion.identity; + if (num) + { + b |= nonIdentityRotationBit; + } + if (isGrounded) + { + b |= isGroundedBit; + } + writer.Write(b); + writer.Write(timestamp); + writer.Write(gameObject); + writer.Write(newPosition); + writer.Write(new PackedUnitVector3(aimDirection)); + writer.Write(moveVector); + if (num) + { + writer.Write(rotation); + } + if (isGrounded) + { + writer.Write(new PackedUnitVector3(groundNormal)); + } + } + + public override void Deserialize(NetworkReader reader) + { + base.Deserialize(reader); + byte b = reader.ReadByte(); + bool num = (b & nonIdentityRotationBit) != 0; + isGrounded = (b & isGroundedBit) != 0; + timestamp = reader.ReadSingle(); + gameObject = reader.ReadGameObject(); + newPosition = reader.ReadVector3(); + aimDirection = reader.ReadPackedUnitVector3().Unpack(); + moveVector = reader.ReadVector3(); + if (num) + { + rotation = reader.ReadQuaternion(); + } + else + { + rotation = Quaternion.identity; + } + if (isGrounded) + { + groundNormal = reader.ReadPackedUnitVector3().Unpack(); + } + } + } + + public struct NetSnapshot + { + public GameObject gameObject; + + public CharacterNetworkTransform.Snapshot snapshot; + } + + private static CharacterNetworkTransformManager instance; + + private CharacterUpdateMessage currentInMessage = new CharacterUpdateMessage(); + + private CharacterUpdateMessage currentOutMessage = new CharacterUpdateMessage(); + + private readonly Queue snapshotQueue = new Queue(); + + private void Awake() + { + instance = this; + } + + [NetworkMessageHandler(msgType = 51, client = true, server = true)] + private static void HandleTransformUpdates(NetworkMessage netMsg) + { + if ((bool)instance) + { + instance.HandleTransformUpdatesInternal(netMsg); + } + } + + private void HandleTransformUpdatesInternal(NetworkMessage netMsg) + { + uint num = netMsg.reader.ReadByte(); + float filteredClientRttFixed = PlatformSystems.networkManager.filteredClientRttFixed; + for (int i = 0; i < num; i++) + { + netMsg.ReadMessage(currentInMessage); + GameObject gameObject = currentInMessage.gameObject; + if (!gameObject || (NetworkServer.active && gameObject.GetComponent().clientAuthorityOwner != netMsg.conn)) + { + continue; + } + CharacterNetworkTransform component = gameObject.GetComponent(); + if ((bool)component && !component.hasEffectiveAuthority) + { + CharacterNetworkTransform.Snapshot snapshot = default(CharacterNetworkTransform.Snapshot); + snapshot.serverTime = currentInMessage.timestamp; + snapshot.position = currentInMessage.newPosition; + snapshot.moveVector = currentInMessage.moveVector; + snapshot.aimDirection = currentInMessage.aimDirection; + snapshot.rotation = currentInMessage.rotation; + snapshot.isGrounded = currentInMessage.isGrounded; + snapshot.groundNormal = currentInMessage.groundNormal; + CharacterNetworkTransform.Snapshot snapshot2 = snapshot; + if (NetworkClient.active) + { + snapshot2.serverTime += filteredClientRttFixed; + } + component.PushSnapshot(snapshot2); + if (NetworkServer.active) + { + snapshotQueue.Enqueue(new NetSnapshot + { + gameObject = component.gameObject, + snapshot = snapshot2 + }); + } + } + } + } + + private void ProcessQueue() + { + if (snapshotQueue.Count != 0) + { + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(51); + int num = Mathf.Min(Mathf.FloorToInt((float)(1000 - networkWriter.Position) / (float)CharacterUpdateMessage.maxNetworkSize), snapshotQueue.Count); + networkWriter.Write((byte)num); + for (int i = 0; i < num; i++) + { + NetSnapshot netSnapshot = snapshotQueue.Dequeue(); + currentOutMessage.gameObject = netSnapshot.gameObject; + currentOutMessage.newPosition = netSnapshot.snapshot.position; + currentOutMessage.aimDirection = netSnapshot.snapshot.aimDirection; + currentOutMessage.moveVector = netSnapshot.snapshot.moveVector; + currentOutMessage.rotation = netSnapshot.snapshot.rotation; + currentOutMessage.isGrounded = netSnapshot.snapshot.isGrounded; + currentOutMessage.timestamp = netSnapshot.snapshot.serverTime; + currentOutMessage.groundNormal = netSnapshot.snapshot.groundNormal; + networkWriter.Write(currentOutMessage); + } + networkWriter.FinishMessage(); + if (NetworkServer.active) + { + NetworkServer.SendWriterToReady(null, networkWriter, QosChannelIndex.characterTransformUnreliable.intVal); + } + else if (ClientScene.readyConnection != null) + { + ClientScene.readyConnection.SendWriter(networkWriter, QosChannelIndex.characterTransformUnreliable.intVal); + } + } + } + + private void FixedUpdate() + { + if (!NetworkManager.singleton || RoR2Application.isInSinglePlayer) + { + return; + } + ReadOnlyCollection readOnlyInstancesList = CharacterNetworkTransform.readOnlyInstancesList; + float fixedTime = Time.fixedTime; + for (int i = 0; i < readOnlyInstancesList.Count; i++) + { + CharacterNetworkTransform characterNetworkTransform = readOnlyInstancesList[i]; + if (characterNetworkTransform.hasEffectiveAuthority && fixedTime - characterNetworkTransform.lastPositionTransmitTime > characterNetworkTransform.positionTransmitInterval) + { + characterNetworkTransform.lastPositionTransmitTime = fixedTime; + snapshotQueue.Enqueue(new NetSnapshot + { + gameObject = characterNetworkTransform.gameObject, + snapshot = characterNetworkTransform.newestNetSnapshot + }); + } + } + while (snapshotQueue.Count > 0) + { + ProcessQueue(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/ClientAuthData.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/ClientAuthData.cs new file mode 100644 index 0000000..5fe9254 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/ClientAuthData.cs @@ -0,0 +1,39 @@ +using Unity; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class ClientAuthData : MessageBase +{ + public PlatformID platformId = PlatformID.nil; + + public byte[] authTicket; + + public string[] entitlements; + + public string password; + + public string version; + + public string modHash; + + public override void Serialize(NetworkWriter writer) + { + GeneratedNetworkCode._WritePlatformID_None(writer, platformId); + writer.WriteBytesFull(authTicket); + GeneratedNetworkCode._WriteArrayString_None(writer, entitlements); + writer.Write(password); + writer.Write(version); + writer.Write(modHash); + } + + public override void Deserialize(NetworkReader reader) + { + platformId = GeneratedNetworkCode._ReadPlatformID_None(reader); + authTicket = reader.ReadBytesAndSize(); + entitlements = GeneratedNetworkCode._ReadArrayString_None(reader); + password = reader.ReadString(); + version = reader.ReadString(); + modHash = reader.ReadString(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/EOSNetworkClient.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/EOSNetworkClient.cs new file mode 100644 index 0000000..779a482 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/EOSNetworkClient.cs @@ -0,0 +1,23 @@ +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class EOSNetworkClient : NetworkClient +{ + public EOSNetworkConnection eosConnection => (EOSNetworkConnection)base.connection; + + public string status => m_AsyncConnect.ToString(); + + public void Connect() + { + Connect("localhost", 0); + m_AsyncConnect = ConnectState.Connected; + base.connection.ForceInitialize(base.hostTopology); + } + + public EOSNetworkClient(NetworkConnection conn) + : base(conn) + { + SetNetworkConnectionClass(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/EOSNetworkConnection.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/EOSNetworkConnection.cs new file mode 100644 index 0000000..2fb3523 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/EOSNetworkConnection.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Epic.OnlineServices; +using Epic.OnlineServices.P2P; +using RoR2.ConVar; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class EOSNetworkConnection : NetworkConnection +{ + private static List instancesList = new List(); + + public bool ignore; + + public static BoolConVar cvNetP2PDebugTransport = new BoolConVar("net_p2p_debug_transport", ConVarFlags.None, "0", "Allows p2p transport information to print to the console."); + + private static BoolConVar cvNetP2PLogMessages = new BoolConVar("net_p2p_log_messages", ConVarFlags.None, "0", "Enables logging of network messages."); + + public ProductUserId LocalUserID { get; } + + public ProductUserId RemoteUserID { get; private set; } + + public EOSNetworkConnection() + { + } + + public EOSNetworkConnection(ProductUserId localUserID, ProductUserId remoteUserID) + { + LocalUserID = localUserID; + RemoteUserID = remoteUserID; + instancesList.Add(this); + } + + public bool SendConnectionRequest() + { + SendPacketOptions sendPacketOptions = default(SendPacketOptions); + sendPacketOptions.LocalUserId = LocalUserID; + sendPacketOptions.RemoteUserId = RemoteUserID; + sendPacketOptions.AllowDelayedDelivery = true; + sendPacketOptions.Channel = 0; + sendPacketOptions.Reliability = PacketReliability.ReliableOrdered; + sendPacketOptions.SocketId = NetworkManagerSystemEOS.socketId; + SendPacketOptions options = sendPacketOptions; + return NetworkManagerSystemEOS.P2pInterface.SendPacket(ref options) == Result.Success; + } + + public override bool TransportSend(byte[] bytes, int numBytes, int channelId, out byte error) + { + if (ignore) + { + error = 0; + return true; + } + logNetworkMessages = cvNetP2PLogMessages.value; + if (LocalUserID == RemoteUserID) + { + TransportReceive(bytes, numBytes, channelId); + error = 0; + _ = cvNetP2PDebugTransport.value; + return true; + } + QosType qOS = NetworkManagerSystem.singleton.connectionConfig.Channels[channelId].QOS; + PacketReliability packetReliability = PacketReliability.ReliableOrdered; + packetReliability = ((qOS != 0 && qOS != QosType.UnreliableFragmented && qOS != QosType.UnreliableSequenced) ? PacketReliability.ReliableOrdered : PacketReliability.UnreliableUnordered); + ArraySegment data = new ArraySegment(bytes, 0, numBytes); + SendPacketOptions sendPacketOptions = default(SendPacketOptions); + sendPacketOptions.AllowDelayedDelivery = true; + sendPacketOptions.Data = data; + sendPacketOptions.Channel = 0; + sendPacketOptions.LocalUserId = LocalUserID; + sendPacketOptions.RemoteUserId = RemoteUserID; + sendPacketOptions.SocketId = NetworkManagerSystemEOS.socketId; + sendPacketOptions.Reliability = packetReliability; + SendPacketOptions options = sendPacketOptions; + if (NetworkManagerSystemEOS.P2pInterface.SendPacket(ref options) == Result.Success) + { + error = 0; + return true; + } + error = 1; + return false; + } + + public override void TransportReceive(byte[] bytes, int numBytes, int channelId) + { + if (!ignore) + { + logNetworkMessages = cvNetP2PLogMessages.value; + base.TransportReceive(bytes, numBytes, channelId); + } + } + + protected override void Dispose(bool disposing) + { + instancesList.Remove(this); + P2PInterface p2PInterface = EOSPlatformManager.GetPlatformInterface().GetP2PInterface(); + if (p2PInterface != null) + { + CloseConnectionOptions closeConnectionOptions = default(CloseConnectionOptions); + closeConnectionOptions.LocalUserId = LocalUserID; + closeConnectionOptions.RemoteUserId = RemoteUserID; + closeConnectionOptions.SocketId = NetworkManagerSystemEOS.socketId; + CloseConnectionOptions options = closeConnectionOptions; + p2PInterface.CloseConnection(ref options); + } + base.Dispose(disposing); + } + + public static EOSNetworkConnection Find(ProductUserId owner, ProductUserId endpoint) + { + return instancesList.Where((EOSNetworkConnection instance) => instance.RemoteUserID == endpoint).FirstOrDefault((EOSNetworkConnection instance) => (object)owner == instance.LocalUserID); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/GenericSceneSpawnPoint.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/GenericSceneSpawnPoint.cs new file mode 100644 index 0000000..adeead7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/GenericSceneSpawnPoint.cs @@ -0,0 +1,22 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class GenericSceneSpawnPoint : MonoBehaviour +{ + public GameObject networkedObjectPrefab; + + private void Start() + { + if (NetworkServer.active) + { + NetworkServer.Spawn(Object.Instantiate(networkedObjectPrefab, base.transform.position, base.transform.rotation)); + base.gameObject.SetActive(value: false); + } + else + { + base.gameObject.SetActive(value: false); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/HostDescription.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/HostDescription.cs new file mode 100644 index 0000000..83539f5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/HostDescription.cs @@ -0,0 +1,212 @@ +using System; +using System.Text; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public struct HostDescription : IEquatable +{ + public enum HostType + { + None, + Self, + Steam, + IPv4, + Pia, + PS4, + EOS, + Playfab + } + + public struct HostingParameters : IEquatable + { + public bool listen; + + public int maxPlayers; + + public bool Equals(HostingParameters other) + { + if (listen == other.listen) + { + return maxPlayers == other.maxPlayers; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is HostingParameters other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (listen.GetHashCode() * 397) ^ maxPlayers; + } + } + + public readonly HostType hostType; + + public readonly PlatformID userID; + + public readonly AddressPortPair addressPortPair; + + public readonly HostingParameters hostingParameters; + + public static readonly HostDescription none = new HostDescription(null); + + private static readonly StringBuilder sharedStringBuilder = new StringBuilder(); + + public bool isRemote + { + get + { + if (hostType != 0) + { + return hostType != HostType.Self; + } + return false; + } + } + + public HostDescription(PlatformID id, HostType type) + { + this = default(HostDescription); + hostType = type; + userID = id; + } + + public HostDescription(AddressPortPair addressPortPair) + { + this = default(HostDescription); + hostType = HostType.IPv4; + this.addressPortPair = addressPortPair; + } + + public HostDescription(HostingParameters hostingParameters) + { + this = default(HostDescription); + hostType = HostType.Self; + this.hostingParameters = hostingParameters; + } + + public bool DescribesCurrentHost() + { + switch (hostType) + { + case HostType.None: + return !NetworkManagerSystem.singleton.isNetworkActive; + case HostType.Self: + if (NetworkServer.active && hostingParameters.listen != NetworkServer.dontListen) + { + return true; + } + return false; + case HostType.Steam: + if (NetworkManagerSystem.singleton.client?.connection is SteamNetworkConnection steamNetworkConnection && steamNetworkConnection.steamId == userID) + { + return true; + } + return false; + case HostType.EOS: + if (NetworkManagerSystem.singleton.client?.connection is EOSNetworkConnection eOSNetworkConnection && eOSNetworkConnection.RemoteUserID == userID.productUserID) + { + return true; + } + return false; + case HostType.IPv4: + { + NetworkConnection networkConnection2 = NetworkManagerSystem.singleton.client?.connection; + if (networkConnection2 != null && networkConnection2.address == addressPortPair.address) + { + return true; + } + return false; + } + case HostType.Pia: + return false; + case HostType.Playfab: + { + NetworkConnection networkConnection = NetworkManagerSystem.singleton.client?.connection; + if (networkConnection != null && networkConnection.address == addressPortPair.address) + { + return true; + } + return false; + } + default: + throw new ArgumentOutOfRangeException(); + } + } + + private HostDescription(object o) + { + this = default(HostDescription); + hostType = HostType.None; + } + + public bool Equals(HostDescription other) + { + if (hostType == other.hostType && userID.Equals(other.userID) && addressPortPair.Equals(other.addressPortPair)) + { + return hostingParameters.Equals(other.hostingParameters); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is HostDescription other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return ((((((int)hostType * 397) ^ userID.GetHashCode()) * 397) ^ addressPortPair.GetHashCode()) * 397) ^ hostingParameters.GetHashCode(); + } + + public override string ToString() + { + sharedStringBuilder.Clear(); + sharedStringBuilder.Append("{ hostType=").Append(hostType); + switch (hostType) + { + case HostType.Self: + sharedStringBuilder.Append(" listen=").Append(hostingParameters.listen); + sharedStringBuilder.Append(" maxPlayers=").Append(hostingParameters.maxPlayers); + break; + case HostType.Steam: + sharedStringBuilder.Append(" steamId=").Append(userID); + break; + case HostType.IPv4: + sharedStringBuilder.Append(" address=").Append(addressPortPair.address); + sharedStringBuilder.Append(" port=").Append(addressPortPair.port); + break; + case HostType.EOS: + sharedStringBuilder.Append(" steamId=").Append(userID.ToString()); + break; + default: + throw new ArgumentOutOfRangeException(); + case HostType.None: + case HostType.Pia: + case HostType.Playfab: + break; + } + sharedStringBuilder.Append(" }"); + return sharedStringBuilder.ToString(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkAnimatorParams.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkAnimatorParams.cs new file mode 100644 index 0000000..ff3f0e7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkAnimatorParams.cs @@ -0,0 +1,197 @@ +using System; +using Unity; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkAnimatorParams : NetworkBehaviour +{ + public Animator targetAnimator; + + public string[] targetAnimatorParamNames; + + public float transmitInterval = 0.1f; + + private NetworkIdentity networkIdentity; + + private static readonly uint animatorParamsDirtyBit; + + private static readonly uint allDirtyBits; + + private int[] targetAnimatorParamHashes; + + private NetworkLerpedFloat[] targetAnimatorParamNetworkValues; + + private float transmitTimerAuthority; + + private bool animatorParamsDirtyAuthority; + + private static int kCmdCmdReceiveAnimatorParams; + + private void Awake() + { + networkIdentity = GetComponent(); + targetAnimatorParamHashes = new int[targetAnimatorParamNames.Length]; + for (int i = 0; i < targetAnimatorParamNames.Length; i++) + { + targetAnimatorParamHashes[i] = Animator.StringToHash(targetAnimatorParamNames[i]); + } + targetAnimatorParamNetworkValues = new NetworkLerpedFloat[targetAnimatorParamNames.Length]; + } + + private void FixedUpdate() + { + if (Util.HasEffectiveAuthority(networkIdentity)) + { + FixedUpdateAuthority(); + } + } + + private void Update() + { + if (!Util.HasEffectiveAuthority(networkIdentity)) + { + ApplyAnimatorParamsNonAuthority(); + } + } + + private void FixedUpdateAuthority() + { + CollectAnimatorParamsAuthority(out var animatorParamsChanged); + animatorParamsDirtyAuthority |= animatorParamsChanged; + transmitTimerAuthority -= Time.fixedDeltaTime; + if (!(transmitTimerAuthority <= 0f)) + { + return; + } + transmitTimerAuthority = transmitInterval; + if (!animatorParamsDirtyAuthority) + { + return; + } + animatorParamsDirtyAuthority = false; + if (NetworkServer.active) + { + SetDirtyBit(animatorParamsDirtyBit); + return; + } + float[] array = new float[targetAnimatorParamNetworkValues.Length]; + for (int i = 0; i < targetAnimatorParamNetworkValues.Length; i++) + { + array[i] = targetAnimatorParamNetworkValues[i].GetAuthoritativeValue(); + } + CallCmdReceiveAnimatorParams(array); + } + + public override bool OnSerialize(NetworkWriter writer, bool initialState) + { + uint num = (initialState ? allDirtyBits : base.syncVarDirtyBits); + bool num2 = (num & animatorParamsDirtyBit) != 0; + writer.WritePackedUInt32(num); + if (num2) + { + for (int i = 0; i < targetAnimatorParamNetworkValues.Length; i++) + { + writer.Write(targetAnimatorParamNetworkValues[i].GetAuthoritativeValue()); + } + } + return num != 0; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if ((reader.ReadPackedUInt32() & animatorParamsDirtyBit) != 0) + { + for (int i = 0; i < targetAnimatorParamNetworkValues.Length; i++) + { + targetAnimatorParamNetworkValues[i].PushValue(reader.ReadSingle()); + } + } + } + + private void ApplyAnimatorParamsNonAuthority() + { + for (int i = 0; i < targetAnimatorParamHashes.Length; i++) + { + targetAnimator.SetFloat(targetAnimatorParamHashes[i], targetAnimatorParamNetworkValues[i].GetCurrentValue(hasAuthority: false)); + } + } + + private void CollectAnimatorParamsAuthority(out bool animatorParamsChanged) + { + animatorParamsChanged = false; + for (int i = 0; i < targetAnimatorParamHashes.Length; i++) + { + float @float = targetAnimator.GetFloat(targetAnimatorParamHashes[i]); + ref NetworkLerpedFloat reference = ref targetAnimatorParamNetworkValues[i]; + float currentValue = reference.GetCurrentValue(hasAuthority: true); + if (@float != currentValue) + { + animatorParamsChanged = true; + reference.SetValueImmediate(@float); + } + } + } + + [Command] + private void CmdReceiveAnimatorParams(float[] animatorParamValues) + { + int i = 0; + for (int num = Math.Min(animatorParamValues.Length, targetAnimatorParamNetworkValues.Length); i < num; i++) + { + targetAnimatorParamNetworkValues[i].PushValue(animatorParamValues[i]); + } + SetDirtyBit(animatorParamsDirtyBit); + } + + static NetworkAnimatorParams() + { + animatorParamsDirtyBit = 1u; + allDirtyBits = animatorParamsDirtyBit; + kCmdCmdReceiveAnimatorParams = -1267054443; + NetworkBehaviour.RegisterCommandDelegate(typeof(NetworkAnimatorParams), kCmdCmdReceiveAnimatorParams, InvokeCmdCmdReceiveAnimatorParams); + NetworkCRC.RegisterBehaviour("NetworkAnimatorParams", 0); + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdReceiveAnimatorParams(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdReceiveAnimatorParams called on client."); + } + else + { + ((NetworkAnimatorParams)obj).CmdReceiveAnimatorParams(GeneratedNetworkCode._ReadArraySingle_None(reader)); + } + } + + public void CallCmdReceiveAnimatorParams(float[] animatorParamValues) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdReceiveAnimatorParams called on server."); + return; + } + if (base.isServer) + { + CmdReceiveAnimatorParams(animatorParamValues); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdReceiveAnimatorParams); + networkWriter.Write(GetComponent().netId); + GeneratedNetworkCode._WriteArraySingle_None(networkWriter, animatorParamValues); + SendCommandInternal(networkWriter, 0, "CmdReceiveAnimatorParams"); + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkChildActivation.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkChildActivation.cs new file mode 100644 index 0000000..153c383 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkChildActivation.cs @@ -0,0 +1,139 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkChildActivation : NetworkBehaviour +{ + private class GameObjectActiveTracker : MonoBehaviour + { + public NetworkChildActivation networkChildActivation; + + public int index = -1; + + private void OnEnable() + { + if ((bool)networkChildActivation) + { + networkChildActivation.SetChildActiveState(index, active: true); + } + } + + private void OnDisable() + { + if ((bool)networkChildActivation) + { + networkChildActivation.SetChildActiveState(index, active: false); + } + } + } + + [Tooltip("The list of child objects this object will handle activating and deactivating over the network. Client and server must have matching lists (ie DO NOT CHANGE AT RUNTIME.)")] + public GameObject[] children = Array.Empty(); + + private GameObjectActiveTracker[] trackers = Array.Empty(); + + private bool[] childrenActiveStates = Array.Empty(); + + private static readonly uint activeStatesDirtyBit = 1u; + + private static readonly uint allDirtyBits = activeStatesDirtyBit; + + private GameObject[] trackedChildren = Array.Empty(); + + private void BuildTrackersForChildren(GameObject[] newTrackedChildren) + { + if (trackedChildren == newTrackedChildren) + { + return; + } + trackedChildren = newTrackedChildren; + for (int i = 0; i < trackers.Length; i++) + { + UnityEngine.Object.Destroy(trackers[i]); + } + Array.Resize(ref trackers, newTrackedChildren.Length); + for (int j = 0; j < newTrackedChildren.Length; j++) + { + GameObject gameObject = newTrackedChildren[j]; + if ((bool)gameObject) + { + GameObjectActiveTracker gameObjectActiveTracker = gameObject.AddComponent(); + gameObjectActiveTracker.index = j; + gameObjectActiveTracker.networkChildActivation = this; + trackers[j] = gameObjectActiveTracker; + SetChildActiveState(j, gameObject.gameObject.activeInHierarchy); + } + } + } + + private void SetChildActiveState(int index, bool active) + { + childrenActiveStates[index] = active; + SetDirtyBit(activeStatesDirtyBit); + } + + private void Awake() + { + Array.Resize(ref childrenActiveStates, children.Length); + Array.Clear(childrenActiveStates, 0, childrenActiveStates.Length); + if (NetworkServer.active) + { + BuildTrackersForChildren(children); + } + } + + private void OnDestroy() + { + if (NetworkServer.active) + { + BuildTrackersForChildren(Array.Empty()); + } + } + + public override bool OnSerialize(NetworkWriter writer, bool initialState) + { + base.OnSerialize(writer, initialState); + uint num = (initialState ? allDirtyBits : base.syncVarDirtyBits); + writer.WritePackedUInt32(num); + if ((num & activeStatesDirtyBit) != 0) + { + writer.WriteBitArray(childrenActiveStates, childrenActiveStates.Length); + } + return num != 0; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + base.OnDeserialize(reader, initialState); + if ((reader.ReadPackedUInt32() & activeStatesDirtyBit) == 0) + { + return; + } + reader.ReadBitArray(childrenActiveStates); + for (int i = 0; i < childrenActiveStates.Length; i++) + { + GameObject gameObject = children[i]; + if ((bool)gameObject) + { + try + { + gameObject.SetActive(childrenActiveStates[i]); + } + catch (Exception message) + { + Debug.LogError(message); + } + } + } + } + + private void UNetVersion() + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkContextActivationGuard.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkContextActivationGuard.cs new file mode 100644 index 0000000..3499d4a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkContextActivationGuard.cs @@ -0,0 +1,37 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkContextActivationGuard : MonoBehaviour +{ + public enum Rule + { + Neutral, + MustBeTrue, + MustBeFalse + } + + public Rule server; + + public Rule client; + + private void Awake() + { + bool flag = true; + flag &= CheckRule(server, NetworkServer.active); + flag &= CheckRule(client, NetworkClient.active); + base.gameObject.SetActive(flag); + } + + private bool CheckRule(Rule rule, bool value) + { + return rule switch + { + Rule.Neutral => true, + Rule.MustBeTrue => value, + Rule.MustBeFalse => !value, + _ => false, + }; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkDateTime.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkDateTime.cs new file mode 100644 index 0000000..1e11de5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkDateTime.cs @@ -0,0 +1,55 @@ +using System; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +[Serializable] +public struct NetworkDateTime : IEquatable +{ + public long _binaryValue; + + public static explicit operator NetworkDateTime(DateTime dateTime) + { + NetworkDateTime result = default(NetworkDateTime); + result._binaryValue = dateTime.ToBinary(); + return result; + } + + public static explicit operator DateTime(NetworkDateTime networkDateTime) + { + return DateTime.FromBinary(networkDateTime._binaryValue); + } + + public static void Serialize(in NetworkDateTime networkDateTime, NetworkWriter writer) + { + writer.Write(networkDateTime._binaryValue); + } + + public static void Deserialize(out NetworkDateTime networkDateTime, NetworkReader reader) + { + networkDateTime._binaryValue = reader.ReadInt64(); + } + + public bool Equals(NetworkDateTime other) + { + return _binaryValue == other._binaryValue; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is NetworkDateTime other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return _binaryValue.GetHashCode(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkEnableObjectIfLocal.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkEnableObjectIfLocal.cs new file mode 100644 index 0000000..7439ea3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkEnableObjectIfLocal.cs @@ -0,0 +1,54 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkEnableObjectIfLocal : NetworkBehaviour +{ + [Tooltip("The GameObject to enable/disable.")] + public GameObject target; + + private void Start() + { + if ((bool)target) + { + target.SetActive(base.hasAuthority); + } + } + + public override void OnStartAuthority() + { + base.OnStartAuthority(); + if ((bool)target) + { + target.SetActive(value: true); + } + } + + public override void OnStopAuthority() + { + if ((bool)target) + { + target.SetActive(value: false); + } + base.OnStopAuthority(); + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool result = default(bool); + return result; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkExtensions.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkExtensions.cs new file mode 100644 index 0000000..94765f8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkExtensions.cs @@ -0,0 +1,41 @@ +using System; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public static class NetworkExtensions +{ + public static void Write(this NetworkWriter writer, in NetworkDateTime networkDateTime) + { + NetworkDateTime.Serialize(in networkDateTime, writer); + } + + public static NetworkDateTime ReadNetworkDateTime(this NetworkReader reader) + { + NetworkDateTime.Deserialize(out var networkDateTime, reader); + return networkDateTime; + } + + public static void WriteNetworkGuid(this NetworkWriter networkWriter, in NetworkGuid guid) + { + guid.Serialize(networkWriter); + } + + public static void WriteGuid(this NetworkWriter networkWriter, in Guid guid) + { + NetworkGuid guid2 = (NetworkGuid)guid; + networkWriter.WriteNetworkGuid(in guid2); + } + + public static NetworkGuid ReadNetworkGuid(this NetworkReader networkReader) + { + NetworkGuid result = default(NetworkGuid); + result.Deserialize(networkReader); + return result; + } + + public static Guid ReadGuid(this NetworkReader networkReader) + { + return (Guid)networkReader.ReadNetworkGuid(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkGuid.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkGuid.cs new file mode 100644 index 0000000..7b5af24 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkGuid.cs @@ -0,0 +1,86 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +[Serializable] +public struct NetworkGuid : IEquatable +{ + [StructLayout(LayoutKind.Explicit)] + private struct ConverterUnion + { + [FieldOffset(0)] + public Guid guildValue; + + [FieldOffset(0)] + public NetworkGuid networkGuidValue; + } + + public ulong _a; + + public ulong _b; + + public static explicit operator NetworkGuid(Guid guid) + { + ConverterUnion converterUnion = default(ConverterUnion); + converterUnion.guildValue = guid; + return converterUnion.networkGuidValue; + } + + public static explicit operator Guid(NetworkGuid networkGuid) + { + ConverterUnion converterUnion = default(ConverterUnion); + converterUnion.networkGuidValue = networkGuid; + return converterUnion.guildValue; + } + + public bool Equals(NetworkGuid other) + { + if (_a == other._a) + { + return _b == other._b; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is NetworkGuid other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (_a.GetHashCode() * 397) ^ _b.GetHashCode(); + } + + public static bool operator ==(NetworkGuid left, NetworkGuid right) + { + return left.Equals(right); + } + + public static bool operator !=(NetworkGuid left, NetworkGuid right) + { + return !left.Equals(right); + } + + public void Serialize(NetworkWriter writer) + { + writer.Write(_a); + writer.Write(_b); + } + + public void Deserialize(NetworkReader reader) + { + _a = reader.ReadUInt64(); + _b = reader.ReadUInt64(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkLoadout.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkLoadout.cs new file mode 100644 index 0000000..6fa74b4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkLoadout.cs @@ -0,0 +1,138 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkLoadout : NetworkBehaviour +{ + private static readonly Loadout temp; + + private readonly Loadout loadout = new Loadout(); + + private static int kCmdCmdSendLoadout; + + public event Action onLoadoutUpdated; + + public void CopyLoadout(Loadout dest) + { + loadout.Copy(dest); + } + + public void SetLoadout(Loadout src) + { + src.Copy(loadout); + if (NetworkServer.active) + { + SetDirtyBit(1u); + } + else if (base.isLocalPlayer) + { + SendLoadoutClient(); + } + OnLoadoutUpdated(); + } + + [Command] + private void CmdSendLoadout(byte[] bytes) + { + NetworkReader reader = new NetworkReader(bytes); + temp.Deserialize(reader); + SetLoadout(temp); + } + + [Client] + private void SendLoadoutClient() + { + if (!NetworkClient.active) + { + Debug.LogWarning("[Client] function 'System.Void RoR2.Networking.NetworkLoadout::SendLoadoutClient()' called on server"); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + loadout.Serialize(networkWriter); + CallCmdSendLoadout(networkWriter.ToArray()); + } + + private void OnLoadoutUpdated() + { + this.onLoadoutUpdated?.Invoke(); + } + + public override bool OnSerialize(NetworkWriter writer, bool initialState) + { + uint num = base.syncVarDirtyBits; + if (initialState) + { + num = 1u; + } + writer.WritePackedUInt32(num); + if ((num & (true ? 1u : 0u)) != 0) + { + loadout.Serialize(writer); + } + return num != 0; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if ((reader.ReadPackedUInt32() & (true ? 1u : 0u)) != 0) + { + temp.Deserialize(reader); + if (!base.isLocalPlayer) + { + temp.Copy(loadout); + OnLoadoutUpdated(); + } + } + } + + static NetworkLoadout() + { + temp = new Loadout(); + kCmdCmdSendLoadout = 1217513894; + NetworkBehaviour.RegisterCommandDelegate(typeof(NetworkLoadout), kCmdCmdSendLoadout, InvokeCmdCmdSendLoadout); + NetworkCRC.RegisterBehaviour("NetworkLoadout", 0); + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdSendLoadout(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdSendLoadout called on client."); + } + else + { + ((NetworkLoadout)obj).CmdSendLoadout(reader.ReadBytesAndSize()); + } + } + + public void CallCmdSendLoadout(byte[] bytes) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdSendLoadout called on server."); + return; + } + if (base.isServer) + { + CmdSendLoadout(bytes); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdSendLoadout); + networkWriter.Write(GetComponent().netId); + networkWriter.WriteBytesFull(bytes); + SendCommandInternal(networkWriter, 0, "CmdSendLoadout"); + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystem.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystem.cs new file mode 100644 index 0000000..7ef1b69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystem.cs @@ -0,0 +1,1568 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using System.Text; +using HG; +using RoR2.ContentManagement; +using RoR2.ConVar; +using RoR2.Orbs; +using RoR2.UI; +using Unity; +using UnityEngine; +using UnityEngine.AddressableAssets; +using UnityEngine.AddressableAssets.ResourceLocators; +using UnityEngine.Networking; +using UnityEngine.ResourceManagement.AsyncOperations; +using UnityEngine.ResourceManagement.ResourceProviders; +using UnityEngine.SceneManagement; + +namespace RoR2.Networking; + +public abstract class NetworkManagerSystem : NetworkManager +{ + public enum CanPlayOnlineState + { + Pending, + Yes, + No + } + + private class NetLogLevelConVar : BaseConVar + { + private static NetLogLevelConVar cvNetLogLevel = new NetLogLevelConVar("net_loglevel", ConVarFlags.Engine, null, "Network log verbosity."); + + public NetLogLevelConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (TextSerialization.TryParseInvariant(newValue, out int result)) + { + LogFilter.currentLogLevel = result; + } + } + + public override string GetString() + { + return TextSerialization.ToStringInvariant(LogFilter.currentLogLevel); + } + } + + private class SvListenConVar : BaseConVar + { + private static SvListenConVar cvSvListen = new SvListenConVar("sv_listen", ConVarFlags.Engine, null, "Whether or not the server will accept connections from other players."); + + public SvListenConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (!NetworkServer.active && TextSerialization.TryParseInvariant(newValue, out int result)) + { + NetworkServer.dontListen = result == 0; + } + } + + public override string GetString() + { + if (!NetworkServer.dontListen) + { + return "1"; + } + return "0"; + } + } + + public class SvMaxPlayersConVar : BaseConVar + { + public static readonly SvMaxPlayersConVar instance = new SvMaxPlayersConVar("sv_maxplayers", ConVarFlags.Engine, null, "Maximum number of players allowed."); + + public int intValue => NetworkManager.singleton.maxConnections; + + public SvMaxPlayersConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (NetworkServer.active) + { + throw new ConCommandException("Cannot change this convar while the server is running."); + } + if ((bool)NetworkManager.singleton && TextSerialization.TryParseInvariant(newValue, out int result)) + { + NetworkManager.singleton.maxConnections = Math.Min(Math.Max(result, 1), RoR2Application.hardMaxPlayers); + } + } + + public override string GetString() + { + if (!NetworkManager.singleton) + { + return "1"; + } + return TextSerialization.ToStringInvariant(NetworkManager.singleton.maxConnections); + } + } + + private class KickMessage : MessageBase + { + public BaseKickReason kickReason; + + public KickMessage() + { + } + + public KickMessage(BaseKickReason kickReason) + { + this.kickReason = kickReason; + } + + public override void Serialize(NetworkWriter writer) + { + base.Serialize(writer); + string text = kickReason?.GetType().FullName ?? string.Empty; + writer.Write(text); + if (!(text == string.Empty)) + { + kickReason.Serialize(writer); + } + } + + public override void Deserialize(NetworkReader reader) + { + base.Deserialize(reader); + string typeName = reader.ReadString(); + Type type = null; + try + { + type = Type.GetType(typeName); + } + catch + { + } + if (type == null || !typeof(BaseKickReason).IsAssignableFrom(type) || type.IsAbstract) + { + kickReason = null; + return; + } + kickReason = (BaseKickReason)Activator.CreateInstance(type); + kickReason.Deserialize(reader); + } + + public bool TryGetDisplayTokenAndFormatParams(out string token, out object[] formatArgs) + { + if (kickReason == null) + { + token = null; + formatArgs = null; + return false; + } + kickReason.GetDisplayTokenAndFormatParams(out token, out formatArgs); + return true; + } + } + + public abstract class BaseKickReason : MessageBase + { + public BaseKickReason() + { + } + + public abstract void GetDisplayTokenAndFormatParams(out string token, out object[] formatArgs); + } + + public class SimpleLocalizedKickReason : BaseKickReason + { + public string baseToken; + + public string[] formatArgs; + + public SimpleLocalizedKickReason() + { + } + + public SimpleLocalizedKickReason(string baseToken, params string[] formatArgs) + { + this.baseToken = baseToken; + this.formatArgs = formatArgs; + } + + public override void GetDisplayTokenAndFormatParams(out string token, out object[] formatArgs) + { + token = baseToken; + object[] array = this.formatArgs; + formatArgs = array; + } + + public override void Serialize(NetworkWriter writer) + { + writer.Write(baseToken); + GeneratedNetworkCode._WriteArrayString_None(writer, formatArgs); + } + + public override void Deserialize(NetworkReader reader) + { + baseToken = reader.ReadString(); + formatArgs = GeneratedNetworkCode._ReadArrayString_None(reader); + } + } + + public class ModMismatchKickReason : BaseKickReason + { + public string[] serverModList = Array.Empty(); + + public ModMismatchKickReason() + { + } + + public ModMismatchKickReason(IEnumerable serverModList) + { + this.serverModList = serverModList.ToArray(); + } + + public override void GetDisplayTokenAndFormatParams(out string token, out object[] formatArgs) + { + IEnumerable networkModList = NetworkModCompatibilityHelper.networkModList; + IEnumerable values = networkModList.Except(serverModList); + IEnumerable values2 = serverModList.Except(networkModList); + token = "KICK_REASON_MOD_MISMATCH"; + object[] array = new string[2] + { + string.Join("\n", values), + string.Join("\n", values2) + }; + formatArgs = array; + } + + public override void Serialize(NetworkWriter writer) + { + GeneratedNetworkCode._WriteArrayString_None(writer, serverModList); + } + + public override void Deserialize(NetworkReader reader) + { + serverModList = GeneratedNetworkCode._ReadArrayString_None(reader); + } + } + + protected class AddPlayerMessage : MessageBase + { + public PlatformID id; + + public byte[] steamAuthTicketData; + + public override void Serialize(NetworkWriter writer) + { + GeneratedNetworkCode._WritePlatformID_None(writer, id); + writer.WriteBytesFull(steamAuthTicketData); + } + + public override void Deserialize(NetworkReader reader) + { + id = GeneratedNetworkCode._ReadPlatformID_None(reader); + steamAuthTicketData = reader.ReadBytesAndSize(); + } + } + + public class SvHostNameConVar : BaseConVar + { + public static readonly SvHostNameConVar instance = new SvHostNameConVar("sv_hostname", ConVarFlags.None, "", "The public name to use for the server if hosting."); + + private string value = "NAME"; + + public event Action onValueChanged; + + public SvHostNameConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + value = newValue; + this.onValueChanged?.Invoke(newValue); + } + + public override string GetString() + { + return value; + } + } + + public class SvPortConVar : BaseConVar + { + public static readonly SvPortConVar instance = new SvPortConVar("sv_port", ConVarFlags.Engine, null, "The port to use for the server if hosting."); + + public ushort value + { + get + { + if (!singleton) + { + return 0; + } + return (ushort)singleton.networkPort; + } + } + + public SvPortConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValueString) + { + if (NetworkServer.active) + { + throw new ConCommandException("Cannot change this convar while the server is running."); + } + if (TextSerialization.TryParseInvariant(newValueString, out ushort result)) + { + singleton.networkPort = result; + } + } + + public override string GetString() + { + return value.ToString(); + } + } + + public class SvIPConVar : BaseConVar + { + public static readonly SvIPConVar instance = new SvIPConVar("sv_ip", ConVarFlags.Engine, null, "The IP for the server to bind to if hosting."); + + public SvIPConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValueString) + { + if (NetworkServer.active) + { + throw new ConCommandException("Cannot change this convar while the server is running."); + } + singleton.serverBindAddress = newValueString; + } + + public override string GetString() + { + if (!singleton) + { + return string.Empty; + } + return singleton.serverBindAddress; + } + } + + public class SvPasswordConVar : BaseConVar + { + public static readonly SvPasswordConVar instance = new SvPasswordConVar("sv_password", ConVarFlags.None, "", "The password to use for the server if hosting."); + + public string value { get; private set; } + + public event Action onValueChanged; + + public SvPasswordConVar(string name, ConVarFlags flags, string defaultValue, string helpText) + : base(name, flags, defaultValue, helpText) + { + } + + public override void SetString(string newValue) + { + if (newValue == null) + { + newValue = ""; + } + if (!(value == newValue)) + { + value = newValue; + this.onValueChanged?.Invoke(value); + } + } + + public override string GetString() + { + return value; + } + } + + protected class AddressablesChangeSceneAsyncOperation : IChangeSceneAsyncOperation + { + private static AsyncOperationHandle? previousLoadOperation; + + private AsyncOperationHandle srcOperation; + + private bool srcOperationIsDone; + + private SceneInstance sceneInstance; + + private bool isActivated; + + private bool _allowSceneActivation; + + public bool isDone { get; private set; } + + public bool allowSceneActivation + { + get + { + return _allowSceneActivation; + } + set + { + if (_allowSceneActivation != value) + { + _allowSceneActivation = value; + ActivateIfReady(); + } + } + } + + public AddressablesChangeSceneAsyncOperation(object key, LoadSceneMode loadMode, bool activateOnLoad) + { + srcOperation = Addressables.LoadSceneAsync(key, loadMode, activateOnLoad); + previousLoadOperation = srcOperation; + srcOperation.Completed += delegate(AsyncOperationHandle v) + { + srcOperationIsDone = true; + sceneInstance = v.Result; + ActivateIfReady(); + }; + allowSceneActivation = activateOnLoad; + } + + private void ActivateIfReady() + { + if (srcOperationIsDone && !isActivated) + { + sceneInstance.ActivateAsync().completed += delegate + { + isDone = true; + }; + } + } + } + + protected static readonly FieldInfo loadingSceneAsyncFieldInfo; + + protected float _unpredictedServerFixedTime; + + protected float _unpredictedServerFixedTimeSmoothed; + + protected float unpredictedServerFixedTimeVelocity; + + protected float _unpredictedServerFrameTime; + + protected float _unpredictedServerFrameTimeSmoothed; + + protected float unpredictedServerFrameTimeVelocity; + + protected static FloatConVar cvNetTimeSmoothRate; + + public float debugServerTime; + + public float debugRTT; + + protected bool isSinglePlayer; + + protected bool actedUponDesiredHost; + + protected float lastDesiredHostSetTime = float.NegativeInfinity; + + protected HostDescription _desiredHost; + + private static bool wasFading; + + protected static readonly string[] sceneWhiteList; + + public static readonly StringConVar cvClPassword; + + protected GameObject serverNetworkSessionInstance; + + protected GameObject serverPauseStopControllerInstance; + + private static NetworkReader DefaultNetworkReader; + + private static readonly FloatConVar svTimeTransmitInterval; + + private float timeTransmitTimer; + + protected bool serverShuttingDown; + + private static readonly Queue clientsReadyDuringLevelTransition; + + public static readonly StringConVar cvSvCustomTags; + + protected static bool isLoadingScene + { + get + { + IChangeSceneAsyncOperation changeSceneAsyncOperation = (IChangeSceneAsyncOperation)loadingSceneAsyncFieldInfo.GetValue(null); + if (changeSceneAsyncOperation != null) + { + return !changeSceneAsyncOperation.isDone; + } + return false; + } + } + + public new static NetworkManagerSystem singleton => (NetworkManagerSystem)NetworkManager.singleton; + + public float unpredictedServerFixedTime => _unpredictedServerFixedTime; + + public float unpredictedServerFixedTimeSmoothed => _unpredictedServerFixedTimeSmoothed; + + public float serverFixedTime => unpredictedServerFixedTimeSmoothed + filteredClientRttFixed; + + public float unpredictedServerFrameTime => _unpredictedServerFrameTime; + + public float unpredictedServerFrameTimeSmoothed => _unpredictedServerFrameTimeSmoothed; + + public float serverFrameTime => unpredictedServerFrameTimeSmoothed + filteredClientRttFrame; + + public HostDescription desiredHost + { + get + { + return _desiredHost; + } + set + { + if (!_desiredHost.Equals(value)) + { + _desiredHost = value; + actedUponDesiredHost = false; + lastDesiredHostSetTime = Time.unscaledTime; + Debug.LogFormat("NetworkManagerSystem.desiredHost={0}", _desiredHost.ToString()); + } + } + } + + public bool clientHasConfirmedQuit { get; private set; } + + protected bool clientIsConnecting + { + get + { + if (client?.connection != null) + { + return !client.isConnected; + } + return false; + } + } + + public float clientRttFixed { get; private set; } + + public float clientRttFrame { get; private set; } + + public float filteredClientRttFixed { get; private set; } + + public float filteredClientRttFrame { get; private set; } + + public bool isHost { get; protected set; } + + public PlatformID clientP2PId { get; protected set; } = PlatformID.nil; + + + public PlatformID serverP2PId { get; protected set; } = PlatformID.nil; + + + public static event Action onStartGlobal; + + public static event Action onStartClientGlobal; + + public static event Action onStopClientGlobal; + + public static event Action onClientConnectGlobal; + + public static event Action onClientDisconnectGlobal; + + public static event Action onStartHostGlobal; + + public static event Action onStopHostGlobal; + + public static event Action onStartServerGlobal; + + public static event Action onStopServerGlobal; + + public static event Action onServerConnectGlobal; + + public static event Action onServerDisconnectGlobal; + + public static event Action onServerSceneChangedGlobal; + + static NetworkManagerSystem() + { + cvNetTimeSmoothRate = new FloatConVar("net_time_smooth_rate", ConVarFlags.None, "1.05", "The smoothing rate for the network time."); + wasFading = false; + sceneWhiteList = new string[3] { "title", "crystalworld", "logbook" }; + cvClPassword = new StringConVar("cl_password", ConVarFlags.None, "", "The password to use when joining a passworded server."); + DefaultNetworkReader = new NetworkReader(); + svTimeTransmitInterval = new FloatConVar("sv_time_transmit_interval", ConVarFlags.Cheat, (1f / 60f).ToString(), "How long it takes for the server to issue a time update to clients."); + clientsReadyDuringLevelTransition = new Queue(); + cvSvCustomTags = new StringConVar("sv_custom_tags", ConVarFlags.None, "", "Comma-delimited custom tags to report to the server browser."); + loadingSceneAsyncFieldInfo = typeof(NetworkManager).GetField("s_LoadingSceneAsync", BindingFlags.Static | BindingFlags.NonPublic); + if (loadingSceneAsyncFieldInfo == null) + { + Debug.LogError("NetworkManager.s_LoadingSceneAsync field could not be found! Make sure to provide a proper implementation for this version of Unity."); + } + } + + public virtual void Init(NetworkManagerConfiguration configurationComponent) + { + base.dontDestroyOnLoad = configurationComponent.DontDestroyOnLoad; + base.runInBackground = configurationComponent.RunInBackground; + base.logLevel = configurationComponent.LogLevel; + base.offlineScene = configurationComponent.OfflineScene; + base.onlineScene = configurationComponent.OnlineScene; + base.playerPrefab = configurationComponent.PlayerPrefab; + base.autoCreatePlayer = configurationComponent.AutoCreatePlayer; + base.playerSpawnMethod = configurationComponent.PlayerSpawnMethod; + base.spawnPrefabs.Clear(); + base.spawnPrefabs.AddRange(configurationComponent.SpawnPrefabs); + base.customConfig = configurationComponent.CustomConfig; + base.maxConnections = configurationComponent.MaxConnections; + base.channels.Clear(); + base.channels.AddRange(configurationComponent.QosChannels); + Run.onRunStartGlobal += ResetRunTime; + } + + private void ResetRunTime(Run run) + { + if (Run.instance != null) + { + Run.instance.NetworkfixedTime = 0f; + Run.instance.time = 0f; + Run.FixedTimeStamp.Update(); + } + } + + protected void InitializeTime() + { + _unpredictedServerFixedTime = 0f; + _unpredictedServerFixedTimeSmoothed = 0f; + unpredictedServerFixedTimeVelocity = 1f; + _unpredictedServerFrameTime = 0f; + _unpredictedServerFrameTimeSmoothed = 0f; + unpredictedServerFrameTimeVelocity = 1f; + } + + protected void UpdateTime(ref float targetValue, ref float currentValue, ref float velocity, float deltaTime) + { + if (!(deltaTime <= 0f)) + { + targetValue += deltaTime; + float num = (targetValue - currentValue) / deltaTime; + float num2 = 1f; + if (velocity == 0f || Mathf.Abs(num) > num2 * 3f) + { + currentValue = targetValue; + velocity = num2; + } + else + { + currentValue += velocity * deltaTime; + velocity = Mathf.MoveTowards(velocity, num, cvNetTimeSmoothRate.value * deltaTime); + } + } + } + + protected static NetworkUser[] GetConnectionNetworkUsers(NetworkConnection conn) + { + List playerControllers = conn.playerControllers; + NetworkUser[] array = new NetworkUser[playerControllers.Count]; + for (int i = 0; i < playerControllers.Count; i++) + { + array[i] = playerControllers[i].gameObject.GetComponent(); + } + return array; + } + + protected abstract void Start(); + + protected void OnDestroy() + { + typeof(NetworkManager).GetMethod("OnDestroy", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, null); + } + + public IEnumerator FireOnStartGlobalEvent() + { + while (Console.instance == null) + { + yield return null; + } + NetworkManagerSystem.onStartGlobal?.Invoke(); + } + + protected void FixedUpdate() + { + UpdateTime(ref _unpredictedServerFixedTime, ref _unpredictedServerFixedTimeSmoothed, ref unpredictedServerFixedTimeVelocity, Time.fixedDeltaTime); + FixedUpdateServer(); + FixedUpdateClient(); + debugServerTime = unpredictedServerFixedTime; + debugRTT = clientRttFrame; + } + + protected abstract void Update(); + + protected abstract void EnsureDesiredHost(); + + public abstract void ForceCloseAllConnections(); + + public bool IsSinglePlayer() + { + return isSinglePlayer; + } + + public void SetSinglePlayerNetworkState() + { + NetworkServer.dontListen = true; + desiredHost = default(HostDescription); + isSinglePlayer = true; + } + + public void ResetDesiredHost() + { + actedUponDesiredHost = false; + singleton.desiredHost = default(HostDescription); + isSinglePlayer = false; + } + + public abstract void CreateLocalLobby(); + + public virtual IEnumerator CanPlayOnline() + { + yield return CanPlayOnlineState.Yes; + } + + public override void OnStartClient(NetworkClient newClient) + { + base.OnStartClient(newClient); + InitializeTime(); + RegisterPrefabs(ContentManager.bodyPrefabs); + RegisterPrefabs(ContentManager.masterPrefabs); + RegisterPrefabs(ContentManager.projectilePrefabs); + RegisterPrefabs(ContentManager.networkedObjectPrefabs); + RegisterPrefabs(ContentManager.gameModePrefabs); + ClientScene.RegisterPrefab(LegacyResourcesAPI.Load("Prefabs/NetworkSession")); + ClientScene.RegisterPrefab(LegacyResourcesAPI.Load("Prefabs/Stage")); + NetworkMessageHandlerAttribute.RegisterClientMessages(newClient); + NetworkManagerSystem.onStartClientGlobal?.Invoke(newClient); + static void RegisterPrefabs(GameObject[] prefabs) + { + for (int i = 0; i < prefabs.Length; i++) + { + ClientScene.RegisterPrefab(prefabs[i]); + } + } + } + + public override void OnStopClient() + { + try + { + NetworkManagerSystem.onStopClientGlobal?.Invoke(); + } + catch (Exception message) + { + Debug.LogError(message); + } + foreach (NetworkClient allClient in NetworkClient.allClients) + { + allClient?.connection?.Disconnect(); + } + ForceCloseAllConnections(); + if (actedUponDesiredHost) + { + singleton.desiredHost = HostDescription.none; + } + base.OnStopClient(); + OrbStorageUtility.Clear(); + } + + public override void OnClientConnect(NetworkConnection conn) + { + base.OnClientConnect(conn); + clientRttFrame = 0f; + filteredClientRttFixed = 0f; + ClientSendAuth(conn); + ClientSetPlayers(conn); + NetworkManagerSystem.onClientConnectGlobal?.Invoke(conn); + } + + public override void OnClientDisconnect(NetworkConnection conn) + { + base.OnClientDisconnect(conn); + NetworkManagerSystem.onClientDisconnectGlobal?.Invoke(conn); + } + + public void ClientAddPlayer(short playerControllerId, NetworkConnection connection = null) + { + foreach (PlayerController localPlayer in ClientScene.localPlayers) + { + if (localPlayer.playerControllerId == playerControllerId && localPlayer.IsValid && (bool)localPlayer.gameObject) + { + Debug.LogFormat("Player {0} already added, aborting.", playerControllerId); + return; + } + } + Debug.LogFormat("Adding local player controller {0} on connection {1}", playerControllerId, connection); + AddPlayerMessage extraMessage = CreateClientAddPlayerMessage(); + ClientScene.AddPlayer(connection, playerControllerId, extraMessage); + } + + protected abstract AddPlayerMessage CreateClientAddPlayerMessage(); + + protected void UpdateClient() + { + UpdateCheckInactiveConnections(); + if (client?.connection != null) + { + filteredClientRttFrame = RttManager.GetConnectionFrameSmoothedRtt(client.connection); + clientRttFrame = RttManager.GetConnectionRTT(client.connection); + } + bool flag = string.IsNullOrEmpty(NetworkManager.networkSceneName); + bool flag2 = (client != null && !ClientScene.ready && !flag) || isLoadingScene; + if (wasFading != flag2) + { + if (flag2) + { + FadeToBlackManager.fadeCount++; + } + else + { + FadeToBlackManager.fadeCount--; + } + wasFading = flag2; + } + } + + protected abstract void UpdateCheckInactiveConnections(); + + protected abstract void StartClient(PlatformID serverID); + + public abstract bool IsConnectedToServer(PlatformID serverID); + + private void FixedUpdateClient() + { + if (NetworkClient.active && client != null && client?.connection != null && client.connection.isConnected) + { + NetworkConnection connection = client.connection; + filteredClientRttFixed = RttManager.GetConnectionFixedSmoothedRtt(connection); + clientRttFixed = RttManager.GetConnectionRTT(connection); + if (!Util.ConnectionIsLocal(connection)) + { + RttManager.Ping(connection, QosChannelIndex.ping.intVal); + } + } + } + + public override void OnClientSceneChanged(NetworkConnection conn) + { + string text = NetworkManager.networkSceneName; + List list = new List(); + bool flag = false; + for (int i = 0; i < SceneManager.sceneCount; i++) + { + string text2 = SceneManager.GetSceneAt(i).name; + list.Add(text2); + if (text2 == text) + { + flag = true; + } + } + if (flag) + { + base.autoCreatePlayer = false; + base.OnClientSceneChanged(conn); + ClientSetPlayers(conn); + FadeToBlackManager.ForceFullBlack(); + } + } + + private void ClientSendAuth(NetworkConnection conn) + { + ClientAuthData data = new ClientAuthData(); + PlatformAuth(ref data, conn); + data.password = cvClPassword.value; + data.version = RoR2Application.GetBuildId(); + data.modHash = NetworkModCompatibilityHelper.networkModHash; + conn.Send(74, data); + } + + protected abstract void PlatformAuth(ref ClientAuthData data, NetworkConnection conn); + + protected void ClientSetPlayers(NetworkConnection conn) + { + ReadOnlyCollection readOnlyLocalUsersList = LocalUserManager.readOnlyLocalUsersList; + for (int i = 0; i < readOnlyLocalUsersList.Count; i++) + { + if (i == 0 || RoR2Application.isInLocalMultiPlayer) + { + Debug.LogError($"For iteration {i}, out of {readOnlyLocalUsersList.Count}"); + ClientAddPlayer((short)readOnlyLocalUsersList[i].id, conn); + } + } + } + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void ClientInit() + { + SceneCatalog.onMostRecentSceneDefChanged += ClientUpdateOfflineScene; + } + + private static void ClientUpdateOfflineScene(SceneDef sceneDef) + { + if ((bool)singleton && sceneDef.isOfflineScene) + { + singleton.offlineScene = sceneDef.cachedName; + } + } + + protected static void EnsureNetworkManagerNotBusy() + { + if (!singleton || (!singleton.serverShuttingDown && !isLoadingScene)) + { + return; + } + throw new ConCommandException("NetworkManager is busy and cannot receive commands."); + } + + [ConCommand(commandName = "client_set_players", flags = ConVarFlags.None, helpText = "Adds network players for all local players. Debug only.")] + private static void CCClientSetPlayers(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformClientSetPlayers(args); + } + } + + protected abstract void PlatformClientSetPlayers(ConCommandArgs args); + + [ConCommand(commandName = "ping", flags = ConVarFlags.None, helpText = "Prints the current round trip time from this client to the server and back.")] + private static void CCPing(ConCommandArgs args) + { + if ((bool)singleton) + { + NetworkConnection networkConnection = singleton?.client?.connection; + if (networkConnection != null) + { + Debug.LogFormat("rtt={0}ms smoothedFrame={1} smoothedFixed={2}", RttManager.GetConnectionRTTInMilliseconds(networkConnection), RttManager.GetConnectionFrameSmoothedRtt(networkConnection), RttManager.GetConnectionFixedSmoothedRtt(networkConnection)); + } + } + } + + [ConCommand(commandName = "set_scene", flags = ConVarFlags.None, helpText = "Changes to the named scene.")] + private static void CCSetScene(ConCommandArgs args) + { + string argString = args.GetArgString(0); + if (!singleton) + { + throw new ConCommandException("set_scene failed: NetworkManagerSystem is not available."); + } + SceneCatalog.GetSceneDefForCurrentScene(); + SceneDef sceneDefFromSceneName = SceneCatalog.GetSceneDefFromSceneName(argString); + if (!sceneDefFromSceneName) + { + throw new ConCommandException("\"" + argString + "\" is not a valid scene."); + } + bool boolValue = Console.CheatsConVar.instance.boolValue; + if (!NetworkManager.singleton) + { + _ = 1; + } + else + _ = NetworkManager.singleton.isNetworkActive; + if (NetworkManager.singleton.isNetworkActive) + { + if (sceneDefFromSceneName.isOfflineScene) + { + throw new ConCommandException("Cannot switch to scene \"" + argString + "\": Cannot switch to offline-only scene while in a network session."); + } + if (!boolValue) + { + throw new ConCommandException("Cannot switch to scene \"" + argString + "\": Cheats must be enabled to switch between online-only scenes."); + } + } + else if (!sceneDefFromSceneName.isOfflineScene) + { + throw new ConCommandException("Cannot switch to scene \"" + argString + "\": Cannot switch to online-only scene while not in a network session."); + } + if ((bool)PauseStopController.instance && PauseStopController.instance.isPaused) + { + PauseStopController.instance.Pause(shouldPause: false); + } + if (NetworkServer.active) + { + Debug.LogFormat("Setting server scene to {0}", argString); + singleton.ServerChangeScene(argString); + return; + } + if (!NetworkClient.active) + { + Debug.LogFormat("Setting offline scene to {0}", argString); + singleton.ServerChangeScene(argString); + return; + } + throw new ConCommandException("Cannot change scene while connected to a remote server."); + } + + [ConCommand(commandName = "scene_list", flags = ConVarFlags.None, helpText = "Prints a list of all available scene names.")] + private static void CCSceneList(ConCommandArgs args) + { + if ((bool)singleton) + { + string[] array = new string[SceneManager.sceneCountInBuildSettings]; + for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) + { + array[i] = $"[{i}]={SceneUtility.GetScenePathByBuildIndex(i)}"; + } + } + } + + [ConCommand(commandName = "dump_network_ids", flags = ConVarFlags.None, helpText = "Lists the network ids of all currently networked game objects.")] + private static void CCDumpNetworkIDs(ConCommandArgs args) + { + if ((bool)singleton) + { + List list = new List(UnityEngine.Object.FindObjectsOfType()); + list.Sort((NetworkIdentity lhs, NetworkIdentity rhs) => (int)(lhs.netId.Value - rhs.netId.Value)); + for (int i = 0; i < list.Count; i++) + { + Debug.LogFormat("{0}={1}", list[i].netId.Value, list[i].gameObject.name); + } + } + } + + [ConCommand(commandName = "disconnect", flags = ConVarFlags.None, helpText = "Disconnect from a server or shut down the current server.")] + private static void CCDisconnect(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformDisconnect(args); + } + } + + protected abstract void PlatformDisconnect(ConCommandArgs args); + + protected void Disconnect() + { + if (!serverShuttingDown && singleton.isNetworkActive) + { + if (NetworkServer.active) + { + singleton.RequestServerShutdown(); + } + else + { + singleton.StopClient(); + } + OrbStorageUtility.Clear(); + } + } + + [ConCommand(commandName = "connect", flags = ConVarFlags.None, helpText = "Connect to a server.")] + private static void CCConnect(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformConnect(args); + } + } + + protected abstract void PlatformConnect(ConCommandArgs args); + + private static void CCConnectP2P(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformConnect(args); + } + } + + protected abstract void PlatformConnectP2P(ConCommandArgs args); + + [ConCommand(commandName = "host", flags = ConVarFlags.None, helpText = "Host a server. First argument is whether or not to listen for incoming connections.")] + private static void CCHost(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformHost(args); + } + } + + protected abstract void PlatformHost(ConCommandArgs args); + + [ConCommand(commandName = "steam_get_p2p_session_state")] + private static void CCSGetP2PSessionState(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformGetP2PSessionState(args); + } + } + + protected abstract void PlatformGetP2PSessionState(ConCommandArgs args); + + [ConCommand(commandName = "kick_steam", flags = ConVarFlags.SenderMustBeServer, helpText = "Kicks the user with the specified steam id from the server.")] + private static void CCKickSteam(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformKick(args); + } + } + + protected abstract void PlatformKick(ConCommandArgs args); + + [ConCommand(commandName = "ban_steam", flags = ConVarFlags.SenderMustBeServer, helpText = "Bans the user with the specified steam id from the server.")] + private static void CCBan(ConCommandArgs args) + { + if ((bool)singleton) + { + singleton.PlatformBan(args); + } + } + + protected abstract void PlatformBan(ConCommandArgs args); + + public virtual bool IsHost() + { + return isHost; + } + + public override void OnStartHost() + { + base.OnStartHost(); + isHost = true; + NetworkManagerSystem.onStartHostGlobal?.Invoke(); + } + + public override void OnStopHost() + { + NetworkManagerSystem.onStopHostGlobal?.Invoke(); + isHost = false; + base.OnStopHost(); + } + + [NetworkMessageHandler(client = true, server = false, msgType = 67)] + private static void HandleKick(NetworkMessage netMsg) + { + KickMessage kickMessage = netMsg.ReadMessage(); + Debug.LogFormat("Received kick message. Reason={0}", kickMessage.kickReason); + singleton.StopClient(); + kickMessage.TryGetDisplayTokenAndFormatParams(out var token, out var formatArgs); + DialogBoxManager.DialogBox(new SimpleDialogBox.TokenParamsPair("DISCONNECTED"), new SimpleDialogBox.TokenParamsPair(token ?? string.Empty, formatArgs), CommonLanguageTokens.ok); + } + + public static void HandleKick(string displayToken) + { + singleton.StopClient(); + DialogBoxManager.DialogBox("DISCONNECTED", displayToken, CommonLanguageTokens.ok); + } + + [NetworkMessageHandler(msgType = 54, client = true)] + private static void HandleUpdateTime(NetworkMessage netMsg) + { + float num = netMsg.reader.ReadSingle(); + singleton._unpredictedServerFixedTime = num; + float num2 = Time.time - Time.fixedTime; + singleton._unpredictedServerFrameTime = num + num2; + } + + [NetworkMessageHandler(msgType = 64, client = true, server = true)] + private static void HandleTest(NetworkMessage netMsg) + { + int num = netMsg.reader.ReadInt32(); + Debug.LogFormat("Received test packet. value={0}", num); + } + + public abstract NetworkConnection GetClient(PlatformID clientId); + + public virtual void InitPlatformServer() + { + } + + public override void OnStartServer() + { + base.OnStartServer(); + NetworkMessageHandlerAttribute.RegisterServerMessages(); + InitializeTime(); + serverNetworkSessionInstance = UnityEngine.Object.Instantiate(RoR2Application.instance.networkSessionPrefab); + serverPauseStopControllerInstance = UnityEngine.Object.Instantiate(RoR2Application.instance.pauseStopController); + InitPlatformServer(); + NetworkManagerSystem.onStartServerGlobal?.Invoke(); + } + + public void FireStartServerGlobalEvent() + { + NetworkManagerSystem.onStartServerGlobal?.Invoke(); + } + + public override void OnStopServer() + { + base.OnStopServer(); + FireStopServerGlobalEvent(); + for (int i = 0; i < NetworkServer.connections.Count; i++) + { + NetworkConnection networkConnection = NetworkServer.connections[i]; + if (networkConnection != null) + { + OnServerDisconnect(networkConnection); + } + } + UnityEngine.Object.Destroy(serverPauseStopControllerInstance); + serverPauseStopControllerInstance = null; + UnityEngine.Object.Destroy(serverNetworkSessionInstance); + serverNetworkSessionInstance = null; + } + + public void FireStopServerGlobalEvent() + { + NetworkManagerSystem.onStopServerGlobal?.Invoke(); + } + + public override void OnServerConnect(NetworkConnection conn) + { + base.OnServerConnect(conn); + } + + public void FireServerConnectGlobalEvent(NetworkConnection conn) + { + NetworkManagerSystem.onServerConnectGlobal?.Invoke(conn); + } + + public override void OnServerDisconnect(NetworkConnection conn) + { + base.OnServerDisconnect(conn); + } + + public void FireServerDisconnectGlobalEvent(NetworkConnection conn) + { + NetworkManagerSystem.onServerDisconnectGlobal?.Invoke(conn); + } + + public abstract void ServerHandleClientDisconnect(NetworkConnection conn); + + public abstract void ServerBanClient(NetworkConnection conn); + + public void ServerKickClient(NetworkConnection conn, BaseKickReason reason) + { + Debug.LogFormat("Kicking client on connection {0}: Reason {1}", conn.connectionId, reason); + conn.SendByChannel(67, new KickMessage(reason), QosChannelIndex.defaultReliable.intVal); + conn.FlushChannels(); + KickClient(conn, reason); + } + + protected abstract void KickClient(NetworkConnection conn, BaseKickReason reason); + + public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) + { + OnServerAddPlayer(conn, playerControllerId, null); + } + + public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) + { + OnServerAddPlayerInternal(conn, playerControllerId, extraMessageReader); + } + + private void OnServerAddPlayerInternal(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) + { + if (base.playerPrefab == null) + { + if (LogFilter.logError) + { + Debug.LogError("The PlayerPrefab is empty on the NetworkManager. Please setup a PlayerPrefab object."); + } + return; + } + if (base.playerPrefab.GetComponent() == null) + { + if (LogFilter.logError) + { + Debug.LogError("The PlayerPrefab does not have a NetworkIdentity. Please add a NetworkIdentity to the player prefab."); + } + return; + } + if (playerControllerId < conn.playerControllers.Count && conn.playerControllers[playerControllerId].IsValid && conn.playerControllers[playerControllerId].gameObject != null) + { + if (LogFilter.logError) + { + Debug.LogErrorFormat("There is already a player at that playerControllerId for this connection, conn = {0}, playerControllerId = {1}.", conn, playerControllerId); + } + return; + } + if (NetworkUser.readOnlyInstancesList.Count >= base.maxConnections) + { + if (LogFilter.logError) + { + Debug.LogError("Cannot add any more players.)"); + } + return; + } + if (extraMessageReader == null) + { + extraMessageReader = DefaultNetworkReader; + } + AddPlayerMessage message = extraMessageReader.ReadMessage(); + Transform startPosition = GetStartPosition(); + GameObject gameObject = ((!(startPosition != null)) ? UnityEngine.Object.Instantiate(base.playerPrefab, Vector3.zero, Quaternion.identity) : UnityEngine.Object.Instantiate(base.playerPrefab, startPosition.position, startPosition.rotation)); + Debug.LogFormat("NetworkManagerSystem.AddPlayerInternal(conn={0}, playerControllerId={1}, extraMessageReader={2}", conn, playerControllerId, extraMessageReader); + NetworkUser component = gameObject.GetComponent(); + Util.ConnectionIsLocal(conn); + component.id = AddPlayerIdFromPlatform(conn, message, (byte)playerControllerId); + Chat.SendPlayerConnectedMessage(component); + NetworkServer.AddPlayerForConnection(conn, gameObject, playerControllerId); + } + + protected abstract NetworkUserId AddPlayerIdFromPlatform(NetworkConnection conn, AddPlayerMessage message, byte playerControllerId); + + protected abstract void UpdateServer(); + + private void FixedUpdateServer() + { + if (!NetworkServer.active) + { + return; + } + timeTransmitTimer -= Time.fixedDeltaTime; + if (timeTransmitTimer <= 0f) + { + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(54); + networkWriter.Write(unpredictedServerFixedTime); + networkWriter.FinishMessage(); + NetworkServer.SendWriterToReady(null, networkWriter, QosChannelIndex.time.intVal); + timeTransmitTimer += svTimeTransmitInterval.value; + } + foreach (NetworkConnection connection in NetworkServer.connections) + { + if (connection != null && !Util.ConnectionIsLocal(connection)) + { + RttManager.Ping(connection, QosChannelIndex.ping.intVal); + } + } + } + + public override void OnServerSceneChanged(string sceneName) + { + base.OnServerSceneChanged(sceneName); + if ((bool)Run.instance) + { + Run.instance.OnServerSceneChanged(sceneName); + } + NetworkManagerSystem.onServerSceneChangedGlobal?.Invoke(sceneName); + while (clientsReadyDuringLevelTransition.Count > 0) + { + NetworkConnection networkConnection = clientsReadyDuringLevelTransition.Dequeue(); + try + { + if (networkConnection.isConnected) + { + OnServerReady(networkConnection); + } + } + catch (Exception ex) + { + Debug.LogErrorFormat("OnServerReady could not be called for client: {0}", ex.Message); + } + } + } + + protected bool IsServerAtMaxConnections() + { + ReadOnlyCollection connections = NetworkServer.connections; + if (connections.Count >= base.maxConnections) + { + int num = 0; + for (int i = 0; i < connections.Count; i++) + { + if (connections[i] != null) + { + num++; + } + } + return num >= base.maxConnections; + } + return false; + } + + private NetworkUser FindNetworkUserForConnectionServer(NetworkConnection connection) + { + ReadOnlyCollection readOnlyInstancesList = NetworkUser.readOnlyInstancesList; + int count = readOnlyInstancesList.Count; + for (int i = 0; i < count; i++) + { + NetworkUser networkUser = readOnlyInstancesList[i]; + if (networkUser.connectionToClient == connection) + { + return networkUser; + } + } + return null; + } + + public int GetConnectingClientCount() + { + int num = 0; + ReadOnlyCollection connections = NetworkServer.connections; + int count = connections.Count; + for (int i = 0; i < count; i++) + { + NetworkConnection networkConnection = connections[i]; + if (networkConnection != null && !FindNetworkUserForConnectionServer(networkConnection)) + { + num++; + } + } + return num; + } + + public void RequestServerShutdown() + { + if (!serverShuttingDown) + { + serverShuttingDown = true; + StartCoroutine(ServerShutdownCoroutine()); + } + } + + private IEnumerator ServerShutdownCoroutine() + { + ReadOnlyCollection connections = NetworkServer.connections; + for (int num = connections.Count - 1; num >= 0; num--) + { + NetworkConnection networkConnection = connections[num]; + if (networkConnection != null && !Util.ConnectionIsLocal(networkConnection)) + { + ServerKickClient(networkConnection, new SimpleLocalizedKickReason("KICK_REASON_SERVERSHUTDOWN")); + } + } + float maxWait = 0.2f; + for (float t = 0f; t < maxWait; t += Time.unscaledDeltaTime) + { + if (CheckConnectionsEmpty()) + { + break; + } + yield return new WaitForEndOfFrame(); + } + if (client != null) + { + StopHost(); + } + else + { + StopServer(); + } + serverShuttingDown = false; + static bool CheckConnectionsEmpty() + { + foreach (NetworkConnection connection in NetworkServer.connections) + { + if (connection != null && !Util.ConnectionIsLocal(connection)) + { + return false; + } + } + return true; + } + } + + private static void ServerHandleReady(NetworkMessage netMsg) + { + if (isLoadingScene) + { + clientsReadyDuringLevelTransition.Enqueue(netMsg.conn); + } + else + { + singleton.OnServerReady(netMsg.conn); + } + } + + private void RegisterServerOverrideMessages() + { + NetworkServer.RegisterHandler(35, ServerHandleReady); + } + + public override void ServerChangeScene(string newSceneName) + { + RegisterServerOverrideMessages(); + base.ServerChangeScene(newSceneName); + } + + private static bool IsAddressablesKeyValid(string key, Type type) + { + foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators) + { + if (resourceLocator.Locate(key, typeof(SceneInstance), out var locations) && locations.Count > 0) + { + return true; + } + } + return false; + } + + protected override IChangeSceneAsyncOperation ChangeSceneImplementation(string newSceneName) + { + IChangeSceneAsyncOperation changeSceneAsyncOperation = null; + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + try + { + SceneDef sceneDef = SceneCatalog.FindSceneDef(newSceneName); + if ((bool)sceneDef) + { + string text = sceneDef.sceneAddress?.AssetGUID; + if (!string.IsNullOrEmpty(text)) + { + if (IsAddressablesKeyValid(text, typeof(SceneInstance))) + { + changeSceneAsyncOperation = new AddressablesChangeSceneAsyncOperation(text, LoadSceneMode.Single, activateOnLoad: false); + } + else + { + stringBuilder.AppendLine("Scene address is invalid. sceneName=\"").Append(newSceneName).Append("\" sceneAddress=\"") + .Append(text) + .Append("\"") + .AppendLine(); + } + } + } + else if (IsAddressablesKeyValid(newSceneName, typeof(SceneInstance))) + { + changeSceneAsyncOperation = new AddressablesChangeSceneAsyncOperation(newSceneName, LoadSceneMode.Single, activateOnLoad: false); + } + if (changeSceneAsyncOperation == null) + { + changeSceneAsyncOperation = base.ChangeSceneImplementation(newSceneName); + if (changeSceneAsyncOperation == null) + { + stringBuilder.Append("SceneManager.LoadSceneAsync(\"").Append(newSceneName).Append("\" failed.") + .AppendLine(); + } + } + return changeSceneAsyncOperation; + } + finally + { + if (changeSceneAsyncOperation == null) + { + Debug.LogError(stringBuilder.ToString()); + } + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystemEOS.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystemEOS.cs new file mode 100644 index 0000000..56a6df4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystemEOS.cs @@ -0,0 +1,642 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Epic.OnlineServices; +using Epic.OnlineServices.Lobby; +using Epic.OnlineServices.P2P; +using Facepunch.Steamworks; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkManagerSystemEOS : NetworkManagerSystem +{ + public ProductUserId myUserId; + + private int packetsRecieved; + + private Dictionary sequenceNumber = new Dictionary(); + + private Dictionary>> outOfOrderPackets = new Dictionary>>(); + + private List epicIdBanList = new List(); + + public static SocketId socketId = new SocketId + { + SocketName = "RoR2EOS" + }; + + public static P2PInterface P2pInterface { get; private set; } + + protected override void Start() + { + myUserId = null; + foreach (QosType channel in base.channels) + { + base.connectionConfig.AddChannel(channel); + } + base.connectionConfig.PacketSize = 1200; + StartCoroutine(FireOnStartGlobalEvent()); + } + + protected override void Update() + { + if (!(EOSLoginManager.loggedInProductId == null)) + { + UpdateTime(ref _unpredictedServerFrameTime, ref _unpredictedServerFrameTimeSmoothed, ref unpredictedServerFrameTimeVelocity, Time.deltaTime); + EnsureDesiredHost(); + UpdateServer(); + UpdateClient(); + UpdateNetworkReceiveLoop(); + } + } + + public void ResetSequencing() + { + packetsRecieved = 0; + sequenceNumber.Clear(); + outOfOrderPackets.Clear(); + } + + private void UpdateNetworkReceiveLoop() + { + if (!(P2pInterface == null)) + { + byte[] array = new byte[base.connectionConfig.PacketSize]; + ArraySegment arraySegment = new ArraySegment(array); + int num = 0; + bool flag = true; + while (flag) + { + ReceivePacketOptions receivePacketOptions = default(ReceivePacketOptions); + receivePacketOptions.LocalUserId = EOSLoginManager.loggedInProductId; + receivePacketOptions.MaxDataSizeBytes = base.connectionConfig.PacketSize; + ReceivePacketOptions options = receivePacketOptions; + num++; + ProductUserId outPeerId; + SocketId outSocketId; + byte outChannel; + uint outBytesWritten; + Result result = P2pInterface.ReceivePacket(ref options, out outPeerId, out outSocketId, out outChannel, arraySegment, out outBytesWritten); + flag = ProcessData(result, outPeerId, arraySegment, (int)outBytesWritten, outChannel); + } + } + } + + private bool ProcessData(Result result, ProductUserId incomingUserId, ArraySegment buf, int outBytesWritten, int channelId) + { + switch (result) + { + case Result.Success: + { + EOSNetworkConnection eOSNetworkConnection = EOSNetworkConnection.Find(myUserId, incomingUserId); + if (eOSNetworkConnection != null) + { + eOSNetworkConnection.TransportReceive(buf.Array, outBytesWritten, 0); + } + else + { + Debug.LogFormat("Rejecting data from sender: Not associated with a registered connection. id={0} dataLength={1}", incomingUserId, buf.Count); + } + return true; + } + case Result.InvalidParameters: + case Result.NotFound: + return false; + default: + Debug.LogError("P2PInterface ReceivePacket returned a failure: " + result); + return false; + } + } + + protected override void EnsureDesiredHost() + { + if (false | serverShuttingDown | base.clientIsConnecting | (NetworkServer.active && NetworkManagerSystem.isLoadingScene) | (!NetworkClient.active && NetworkManagerSystem.isLoadingScene)) + { + return; + } + bool isAnyUserSignedIn = LocalUserManager.isAnyUserSignedIn; + if (base.desiredHost.isRemote && !isAnyUserSignedIn) + { + return; + } + if (isNetworkActive && !actedUponDesiredHost && !base.desiredHost.DescribesCurrentHost()) + { + Disconnect(); + } + else + { + if (actedUponDesiredHost) + { + return; + } + int maxPlayers = RoR2Application.maxPlayers; + if (base.desiredHost.hostType == HostDescription.HostType.Self) + { + if (NetworkServer.active) + { + return; + } + actedUponDesiredHost = true; + base.maxConnections = base.desiredHost.hostingParameters.maxPlayers; + NetworkServer.dontListen = !base.desiredHost.hostingParameters.listen; + if (!isAnyUserSignedIn) + { + StartServer(base.connectionConfig, maxPlayers); + } + else + { + StartHost(base.connectionConfig, maxPlayers); + } + } + if (base.desiredHost.hostType == HostDescription.HostType.EOS && Time.unscaledTime - lastDesiredHostSetTime >= 0f) + { + actedUponDesiredHost = true; + StartClient(base.desiredHost.userID.productUserID); + } + if (base.desiredHost.hostType == HostDescription.HostType.IPv4 && Time.unscaledTime - lastDesiredHostSetTime >= 0f) + { + actedUponDesiredHost = true; + Debug.LogFormat("Attempting connection. ip={0} port={1}", base.desiredHost.addressPortPair.address, base.desiredHost.addressPortPair.port); + NetworkManagerSystem.singleton.networkAddress = base.desiredHost.addressPortPair.address; + NetworkManagerSystem.singleton.networkPort = base.desiredHost.addressPortPair.port; + NetworkManagerSystem.singleton.StartClient(matchInfo, base.connectionConfig); + } + } + } + + public override void ForceCloseAllConnections() + { + foreach (NetworkConnection connection in NetworkServer.connections) + { + if (connection is EOSNetworkConnection eOSNetworkConnection) + { + CloseConnectionOptions closeConnectionOptions = default(CloseConnectionOptions); + closeConnectionOptions.LocalUserId = eOSNetworkConnection.LocalUserID; + closeConnectionOptions.RemoteUserId = eOSNetworkConnection.RemoteUserID; + closeConnectionOptions.SocketId = socketId; + CloseConnectionOptions options = closeConnectionOptions; + P2pInterface.CloseConnection(ref options); + } + } + if (client?.connection is EOSNetworkConnection eOSNetworkConnection2) + { + CloseConnectionOptions closeConnectionOptions = default(CloseConnectionOptions); + closeConnectionOptions.LocalUserId = eOSNetworkConnection2.LocalUserID; + closeConnectionOptions.RemoteUserId = eOSNetworkConnection2.RemoteUserID; + closeConnectionOptions.SocketId = socketId; + CloseConnectionOptions options2 = closeConnectionOptions; + P2pInterface.CloseConnection(ref options2); + } + myUserId = null; + } + + public override NetworkConnection GetClient(PlatformID clientID) + { + if (!NetworkServer.active) + { + return null; + } + if (clientID.productUserID == myUserId && NetworkServer.connections.Count > 0) + { + return NetworkServer.connections[0]; + } + foreach (NetworkConnection connection in NetworkServer.connections) + { + if (connection is EOSNetworkConnection eOSNetworkConnection && eOSNetworkConnection.RemoteUserID == clientID.productUserID) + { + return eOSNetworkConnection; + } + } + Debug.LogError("Client not found"); + return null; + } + + public override void OnServerConnect(NetworkConnection conn) + { + base.OnServerConnect(conn); + if (NetworkUser.readOnlyInstancesList.Count >= base.maxConnections) + { + ServerKickClient(conn, new SimpleLocalizedKickReason("KICK_REASON_SERVERFULL")); + } + else + { + FireServerConnectGlobalEvent(conn); + } + } + + public override void OnServerDisconnect(NetworkConnection conn) + { + if (conn == null) + { + return; + } + FireServerDisconnectGlobalEvent(conn); + if (conn?.clientOwnedObjects != null) + { + foreach (NetworkInstanceId item in new HashSet(conn.clientOwnedObjects)) + { + if (item.IsEmpty()) + { + break; + } + GameObject gameObject = NetworkServer.FindLocalObject(item); + if (gameObject != null && (bool)gameObject.GetComponent() && gameObject.TryGetComponent(out var component) && component.clientAuthorityOwner == conn) + { + component.RemoveClientAuthority(conn); + } + } + } + List list = conn?.playerControllers; + for (int i = 0; i < list.Count; i++) + { + if (list[i]?.gameObject != null && list[i].gameObject.TryGetComponent(out var component2)) + { + Chat.SendPlayerDisconnectedMessage(component2); + } + } + if (conn is EOSNetworkConnection eOSNetworkConnection) + { + _ = eOSNetworkConnection.RemoteUserID != null; + } + base.OnServerDisconnect(conn); + } + + public override void OnStartServer() + { + base.OnStartServer(); + ServerManagerBase.StartServer(); + InitP2P(); + NetworkMessageHandlerAttribute.RegisterServerMessages(); + InitializeTime(); + if (NetworkManager.singleton == null) + { + serverNetworkSessionInstance = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkSession")); + } + else + { + serverNetworkSessionInstance = NetworkManager.singleton.gameObject; + } + FireStartServerGlobalEvent(); + } + + public override void OnStopServer() + { + FireStopServerGlobalEvent(); + for (int i = 0; i < NetworkServer.connections.Count; i++) + { + NetworkConnection networkConnection = NetworkServer.connections[i]; + if (networkConnection != null) + { + OnServerDisconnect(networkConnection); + } + } + serverNetworkSessionInstance = null; + ServerManagerBase.StopServer(); + myUserId = null; + base.OnStopServer(); + } + + public override void ServerBanClient(NetworkConnection conn) + { + if (conn is EOSNetworkConnection eOSNetworkConnection) + { + epicIdBanList.Add(eOSNetworkConnection.RemoteUserID); + } + } + + protected override NetworkUserId AddPlayerIdFromPlatform(NetworkConnection conn, AddPlayerMessage message, byte playerControllerId) + { + NetworkUserId result = NetworkUserId.FromIp(conn.address, playerControllerId); + PlatformID? platformID = ServerAuthManager.FindAuthData(conn)?.platformId; + if (platformID.HasValue) + { + if (platformID.Value.isSteam) + { + Debug.LogError("THIS SHOULD NOT HAPPEN INSIDE AN EOS GAME!"); + } + result = new NetworkUserId(platformID.Value.stringID, playerControllerId); + } + return result; + } + + protected override void KickClient(NetworkConnection conn, BaseKickReason reason) + { + if (conn is EOSNetworkConnection eOSNetworkConnection) + { + eOSNetworkConnection.ignore = true; + } + } + + public override void ServerHandleClientDisconnect(NetworkConnection conn) + { + OnServerDisconnect(conn); + conn.InvokeHandlerNoData(33); + conn.Disconnect(); + conn.Dispose(); + if (conn is EOSNetworkConnection) + { + NetworkServer.RemoveExternalConnection(conn.connectionId); + } + } + + protected override void UpdateServer() + { + } + + public override void OnStartClient(NetworkClient newClient) + { + base.OnStartClient(newClient); + InitP2P(); + } + + public override void OnClientDisconnect(NetworkConnection conn) + { + if (conn is EOSNetworkConnection eOSNetworkConnection) + { + Debug.LogFormat("Closing connection with remote ID: {0}", eOSNetworkConnection.RemoteUserID); + } + base.OnClientDisconnect(conn); + } + + protected override AddPlayerMessage CreateClientAddPlayerMessage() + { + if (client != null) + { + return new AddPlayerMessage + { + id = new PlatformID(EOSLoginManager.loggedInProductId), + steamAuthTicketData = Array.Empty() + }; + } + return new AddPlayerMessage + { + id = default(PlatformID), + steamAuthTicketData = Array.Empty() + }; + } + + protected override void UpdateCheckInactiveConnections() + { + } + + protected override void StartClient(PlatformID serverID) + { + StartClient(serverID.productUserID); + } + + protected override void PlatformAuth(ref ClientAuthData authData, NetworkConnection conn) + { + authData.platformId = new PlatformID(EOSLoginManager.loggedInProductId); + authData.entitlements = PlatformSystems.entitlementsSystem.BuildEntitlements(); + authData.authTicket = Client.Instance.Auth.GetAuthSessionTicket().Data; + } + + private void StartClient(ProductUserId remoteUserId) + { + if (!NetworkServer.active) + { + NetworkManager.networkSceneName = ""; + } + string text = ""; + if (isNetworkActive) + { + text += "isNetworkActive "; + } + if (NetworkClient.active) + { + text += "NetworkClient.active "; + } + if (NetworkServer.active) + { + text += "NetworkClient.active "; + } + if (NetworkManagerSystem.isLoadingScene) + { + text += "isLoadingScene "; + } + if (text != "") + { + RoR2Application.onNextUpdate += delegate + { + }; + } + EOSNetworkConnection eOSNetworkConnection = new EOSNetworkConnection(EOSLoginManager.loggedInProductId, remoteUserId); + EOSNetworkClient eOSNetworkClient = new EOSNetworkClient(eOSNetworkConnection); + eOSNetworkClient.Configure(base.connectionConfig, 1); + UseExternalClient(eOSNetworkClient); + eOSNetworkClient.Connect(); + Debug.LogFormat("Initiating connection to server {0}...", remoteUserId); + if (!eOSNetworkConnection.SendConnectionRequest()) + { + Debug.LogFormat("Failed to send connection request to server {0}.", remoteUserId); + } + } + + public override bool IsConnectedToServer(PlatformID serverID) + { + if (client == null || !client.connection.isConnected) + { + return false; + } + if (client.connection is EOSNetworkConnection eOSNetworkConnection) + { + return eOSNetworkConnection.RemoteUserID == serverID.productUserID; + } + if (client.connection.address == "localServer") + { + return serverID == base.serverP2PId; + } + return false; + } + + private void OnConnectionRequested(ref OnIncomingConnectionRequestInfo connectionRequestInfo) + { + bool flag = false; + if (connectionRequestInfo.SocketId.Value.SocketName == socketId.SocketName) + { + if (NetworkServer.active) + { + flag = !NetworkServer.dontListen && !epicIdBanList.Contains(connectionRequestInfo.RemoteUserId) && !IsServerAtMaxConnections(); + } + else if (client is EOSNetworkClient eOSNetworkClient && eOSNetworkClient.eosConnection.RemoteUserID == connectionRequestInfo.RemoteUserId) + { + flag = true; + } + } + if (flag) + { + AcceptConnectionOptions acceptConnectionOptions = default(AcceptConnectionOptions); + acceptConnectionOptions.LocalUserId = connectionRequestInfo.LocalUserId; + acceptConnectionOptions.RemoteUserId = connectionRequestInfo.RemoteUserId; + acceptConnectionOptions.SocketId = socketId; + AcceptConnectionOptions options = acceptConnectionOptions; + P2pInterface.AcceptConnection(ref options); + CreateServerP2PConnectionWithPeer(connectionRequestInfo.RemoteUserId); + } + } + + public void CreateServerP2PConnectionWithPeer(ProductUserId peer) + { + EOSNetworkConnection eOSNetworkConnection = new EOSNetworkConnection(myUserId, peer); + eOSNetworkConnection.ForceInitialize(NetworkServer.hostTopology); + int num = -1; + ReadOnlyCollection connections = NetworkServer.connections; + for (int i = 1; i < connections.Count; i++) + { + if (connections[i] == null) + { + num = i; + break; + } + } + if (num == -1) + { + num = connections.Count; + } + eOSNetworkConnection.connectionId = num; + NetworkServer.AddExternalConnection(eOSNetworkConnection); + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(32); + networkWriter.FinishMessage(); + eOSNetworkConnection.SendWriter(networkWriter, QosChannelIndex.defaultReliable.intVal); + } + + protected void InitP2P() + { + if (P2pInterface == null) + { + P2pInterface = EOSPlatformManager.GetPlatformInterface().GetP2PInterface(); + AddNotifyPeerConnectionRequestOptions addNotifyPeerConnectionRequestOptions = default(AddNotifyPeerConnectionRequestOptions); + addNotifyPeerConnectionRequestOptions.LocalUserId = EOSLoginManager.loggedInProductId; + addNotifyPeerConnectionRequestOptions.SocketId = socketId; + AddNotifyPeerConnectionRequestOptions options = addNotifyPeerConnectionRequestOptions; + P2pInterface.AddNotifyPeerConnectionRequest(ref options, null, OnConnectionRequested); + AddNotifyPeerConnectionClosedOptions addNotifyPeerConnectionClosedOptions = default(AddNotifyPeerConnectionClosedOptions); + addNotifyPeerConnectionClosedOptions.LocalUserId = EOSLoginManager.loggedInProductId; + addNotifyPeerConnectionClosedOptions.SocketId = socketId; + AddNotifyPeerConnectionClosedOptions options2 = addNotifyPeerConnectionClosedOptions; + P2pInterface.AddNotifyPeerConnectionClosed(ref options2, null, OnConnectionClosed); + } + myUserId = EOSLoginManager.loggedInProductId; + base.serverP2PId = new PlatformID(myUserId); + } + + private void OnConnectionClosed(ref OnRemoteConnectionClosedInfo connectionRequestInfo) + { + EOSNetworkConnection eOSNetworkConnection = EOSNetworkConnection.Find(myUserId, connectionRequestInfo.RemoteUserId); + if (client != null && client.connection == eOSNetworkConnection) + { + eOSNetworkConnection.InvokeHandlerNoData(33); + eOSNetworkConnection.Disconnect(); + eOSNetworkConnection.Dispose(); + } + if (NetworkServer.active && NetworkServer.connections.IndexOf(eOSNetworkConnection) != -1) + { + ServerHandleClientDisconnect(eOSNetworkConnection); + } + } + + protected override void PlatformClientSetPlayers(ConCommandArgs args) + { + if (client != null && client.connection != null) + { + ClientSetPlayers(client.connection); + } + } + + protected override void PlatformConnectP2P(ConCommandArgs args) + { + } + + protected override void PlatformDisconnect(ConCommandArgs args) + { + NetworkManagerSystem.singleton.desiredHost = HostDescription.none; + } + + protected override void PlatformConnect(ConCommandArgs args) + { + AddressPortPair argAddressPortPair = args.GetArgAddressPortPair(0); + if ((bool)NetworkManagerSystem.singleton) + { + NetworkManagerSystem.EnsureNetworkManagerNotBusy(); + Debug.LogFormat("Parsed address={0} port={1}. Setting desired host.", argAddressPortPair.address, argAddressPortPair.port); + NetworkManagerSystem.singleton.desiredHost = new HostDescription(argAddressPortPair); + } + } + + protected override void PlatformHost(ConCommandArgs args) + { + if (!NetworkManagerSystem.singleton) + { + return; + } + bool argBool = args.GetArgBool(0); + if (PlatformSystems.lobbyManager.isInLobby && !PlatformSystems.lobbyManager.ownsLobby) + { + return; + } + bool flag = false; + if (NetworkServer.active) + { + flag = true; + } + if (!flag) + { + int maxPlayers = SvMaxPlayersConVar.instance.intValue; + if (PlatformSystems.lobbyManager.isInLobby) + { + LobbyDetailsCopyInfoOptions options = default(LobbyDetailsCopyInfoOptions); + maxPlayers = (int)(((PlatformSystems.lobbyManager as EOSLobbyManager).CurrentLobbyDetails.CopyInfo(ref options, out var outLobbyDetailsInfo) == Result.Success) ? outLobbyDetailsInfo.Value.MaxMembers : 0); + } + NetworkManagerSystem.singleton.desiredHost = new HostDescription(new HostDescription.HostingParameters + { + listen = argBool, + maxPlayers = maxPlayers + }); + } + } + + protected override void PlatformGetP2PSessionState(ConCommandArgs args) + { + CheckSteamworks(); + args.GetArgPlatformID(0); + _ = (bool)NetworkManagerSystem.singleton; + } + + protected override void PlatformKick(ConCommandArgs args) + { + CheckSteamworks(); + PlatformID argPlatformID = args.GetArgPlatformID(0); + NetworkConnection networkConnection = NetworkManagerSystem.singleton.GetClient(argPlatformID); + if (networkConnection != null) + { + NetworkManagerSystem.singleton.ServerKickClient(networkConnection, new SimpleLocalizedKickReason("KICK_REASON_KICK")); + } + } + + protected override void PlatformBan(ConCommandArgs args) + { + CheckSteamworks(); + PlatformID argPlatformID = args.GetArgPlatformID(0); + NetworkConnection networkConnection = NetworkManagerSystem.singleton.GetClient(argPlatformID); + if (networkConnection != null) + { + NetworkManagerSystem.singleton.ServerBanClient(networkConnection); + NetworkManagerSystem.singleton.ServerKickClient(networkConnection, new SimpleLocalizedKickReason("KICK_REASON_BAN")); + } + } + + public static void CheckSteamworks() + { + if (Client.Instance == null) + { + throw new ConCommandException("Steamworks not available."); + } + } + + public override void CreateLocalLobby() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystemSteam.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystemSteam.cs new file mode 100644 index 0000000..fb9a784 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkManagerSystemSteam.cs @@ -0,0 +1,666 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Facepunch.Steamworks; +using RoR2.ConVar; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkManagerSystemSteam : NetworkManagerSystem +{ + private BaseSteamworks clientSteamworks; + + private BaseSteamworks serverSteamworks; + + protected List steamIdBanList = new List(); + + private static readonly BoolConVar cvSteamP2PUseSteamServer = new BoolConVar("steam_p2p_use_steam_server", ConVarFlags.None, "0", "Whether or not to use the Steam server interface to receive network traffic. Setting to false will cause the traffic to be handled by the Steam client interface instead. Only takes effect on server startup."); + + protected override void Start() + { + foreach (QosType channel in base.channels) + { + base.connectionConfig.AddChannel(channel); + } + base.connectionConfig.PacketSize = 1200; + StartCoroutine(FireOnStartGlobalEvent()); + } + + protected override void Update() + { + UpdateTime(ref _unpredictedServerFrameTime, ref _unpredictedServerFrameTimeSmoothed, ref unpredictedServerFrameTimeVelocity, Time.deltaTime); + EnsureDesiredHost(); + UpdateServer(); + UpdateClient(); + } + + protected override void EnsureDesiredHost() + { + if ((false | serverShuttingDown | base.clientIsConnecting | (NetworkServer.active && NetworkManagerSystem.isLoadingScene) | (!NetworkClient.active && NetworkManagerSystem.isLoadingScene)) || !SystemInitializerAttribute.hasExecuted) + { + return; + } + bool isAnyUserSignedIn = LocalUserManager.isAnyUserSignedIn; + if (base.desiredHost.isRemote && !isAnyUserSignedIn) + { + return; + } + if (isNetworkActive && !actedUponDesiredHost && !base.desiredHost.DescribesCurrentHost()) + { + Disconnect(); + } + else + { + if (actedUponDesiredHost) + { + return; + } + if (base.desiredHost.hostType == HostDescription.HostType.Self) + { + if (NetworkServer.active) + { + return; + } + actedUponDesiredHost = true; + base.maxConnections = base.desiredHost.hostingParameters.maxPlayers; + NetworkServer.dontListen = !base.desiredHost.hostingParameters.listen; + if (!isAnyUserSignedIn) + { + StartServer(base.connectionConfig, 4); + } + else + { + StartHost(base.connectionConfig, 4); + } + } + if (base.desiredHost.hostType == HostDescription.HostType.Steam && Time.unscaledTime - lastDesiredHostSetTime >= 0f) + { + actedUponDesiredHost = true; + StartClient(base.desiredHost.userID); + } + if (base.desiredHost.hostType == HostDescription.HostType.IPv4 && Time.unscaledTime - lastDesiredHostSetTime >= 0f) + { + actedUponDesiredHost = true; + Debug.LogFormat("Attempting connection. ip={0} port={1}", base.desiredHost.addressPortPair.address, base.desiredHost.addressPortPair.port); + NetworkManagerSystem.singleton.networkAddress = base.desiredHost.addressPortPair.address; + NetworkManagerSystem.singleton.networkPort = base.desiredHost.addressPortPair.port; + NetworkManagerSystem.singleton.StartClient(); + } + } + } + + public override void ForceCloseAllConnections() + { + Facepunch.Steamworks.Networking networking = Client.Instance?.Networking; + if (networking == null) + { + return; + } + foreach (NetworkConnection connection in NetworkServer.connections) + { + if (connection is SteamNetworkConnection steamNetworkConnection) + { + networking.CloseSession(steamNetworkConnection.steamId.ID); + } + } + if (client?.connection is SteamNetworkConnection steamNetworkConnection2) + { + networking.CloseSession(steamNetworkConnection2.steamId.ID); + } + } + + public override NetworkConnection GetClient(PlatformID clientID) + { + if (!NetworkServer.active) + { + return null; + } + if (clientID.ID == Client.Instance.SteamId && NetworkServer.connections.Count > 0) + { + return NetworkServer.connections[0]; + } + foreach (NetworkConnection connection in NetworkServer.connections) + { + if (connection is SteamNetworkConnection { steamId: var steamId } steamNetworkConnection && steamId.value == clientID.value) + { + return steamNetworkConnection; + } + } + Debug.LogError("Client not found"); + return null; + } + + public override void OnServerConnect(NetworkConnection conn) + { + base.OnServerConnect(conn); + if (NetworkUser.readOnlyInstancesList.Count >= base.maxConnections) + { + ServerKickClient(conn, new SimpleLocalizedKickReason("KICK_REASON_SERVERFULL")); + } + else + { + FireServerConnectGlobalEvent(conn); + } + } + + public override void OnServerDisconnect(NetworkConnection conn) + { + FireServerDisconnectGlobalEvent(conn); + if (conn.clientOwnedObjects != null) + { + foreach (NetworkInstanceId item in new HashSet(conn.clientOwnedObjects)) + { + GameObject gameObject = NetworkServer.FindLocalObject(item); + if (gameObject != null && (bool)gameObject.GetComponent()) + { + NetworkIdentity component = gameObject.GetComponent(); + if ((bool)component && component.clientAuthorityOwner == conn) + { + component.RemoveClientAuthority(conn); + } + } + } + } + List playerControllers = conn.playerControllers; + for (int i = 0; i < playerControllers.Count; i++) + { + NetworkUser component2 = playerControllers[i].gameObject.GetComponent(); + if ((bool)component2) + { + Chat.SendPlayerDisconnectedMessage(component2); + } + } + if (conn is SteamNetworkConnection) + { + Debug.LogFormat("Closing connection with steamId {0}", ((SteamNetworkConnection)conn).steamId); + } + base.OnServerDisconnect(conn); + } + + public override void InitPlatformServer() + { + ServerManagerBase.StartServer(); + InitP2P(); + } + + public override void OnStopServer() + { + FireStopServerGlobalEvent(); + for (int i = 0; i < NetworkServer.connections.Count; i++) + { + NetworkConnection networkConnection = NetworkServer.connections[i]; + if (networkConnection != null) + { + OnServerDisconnect(networkConnection); + } + } + if ((bool)serverNetworkSessionInstance) + { + UnityEngine.Object.Destroy(serverNetworkSessionInstance); + } + serverNetworkSessionInstance = null; + ServerManagerBase.StopServer(); + } + + public override void ServerBanClient(NetworkConnection conn) + { + if (conn is SteamNetworkConnection steamNetworkConnection) + { + steamIdBanList.Add(steamNetworkConnection.steamId); + } + } + + protected override NetworkUserId AddPlayerIdFromPlatform(NetworkConnection conn, AddPlayerMessage message, byte playerControllerId) + { + NetworkUserId result = NetworkUserId.FromIp(conn.address, playerControllerId); + PlatformID platformID = ServerAuthManager.FindAuthData(conn)?.platformId ?? PlatformID.nil; + if (platformID != PlatformID.nil) + { + result = NetworkUserId.FromId(platformID.ID, playerControllerId); + } + return result; + } + + protected override void KickClient(NetworkConnection conn, BaseKickReason reason) + { + if (conn is SteamNetworkConnection steamNetworkConnection) + { + steamNetworkConnection.ignore = true; + } + } + + public override void ServerHandleClientDisconnect(NetworkConnection conn) + { + OnServerDisconnect(conn); + conn.InvokeHandlerNoData(33); + conn.Disconnect(); + conn.Dispose(); + if (conn is SteamNetworkConnection) + { + NetworkServer.RemoveExternalConnection(conn.connectionId); + } + } + + protected override void UpdateServer() + { + if (!NetworkServer.active) + { + return; + } + ReadOnlyCollection connections = NetworkServer.connections; + for (int num = connections.Count - 1; num >= 0; num--) + { + if (connections[num] is SteamNetworkConnection steamNetworkConnection) + { + Facepunch.Steamworks.Networking.P2PSessionState sessionState = default(Facepunch.Steamworks.Networking.P2PSessionState); + if (Client.Instance.Networking.GetP2PSessionState(steamNetworkConnection.steamId.ID, ref sessionState) && sessionState.Connecting == 0 && sessionState.ConnectionActive == 0) + { + ServerHandleClientDisconnect(steamNetworkConnection); + } + } + } + } + + public override void OnStartClient(NetworkClient newClient) + { + base.OnStartClient(newClient); + InitP2P(); + } + + public override void OnClientConnect(NetworkConnection conn) + { + base.OnClientConnect(conn); + } + + public override void OnClientDisconnect(NetworkConnection conn) + { + if (conn is SteamNetworkConnection steamNetworkConnection) + { + Debug.LogFormat("Closing connection with steamId {0}", steamNetworkConnection.steamId); + } + base.OnClientDisconnect(conn); + } + + protected override AddPlayerMessage CreateClientAddPlayerMessage() + { + if (Client.Instance != null) + { + return new AddPlayerMessage + { + id = new PlatformID(Client.Instance.SteamId), + steamAuthTicketData = Client.Instance.Auth.GetAuthSessionTicket().Data + }; + } + return new AddPlayerMessage + { + id = default(PlatformID), + steamAuthTicketData = Array.Empty() + }; + } + + protected override void UpdateCheckInactiveConnections() + { + if (client?.connection is SteamNetworkConnection) + { + Facepunch.Steamworks.Networking.P2PSessionState sessionState = default(Facepunch.Steamworks.Networking.P2PSessionState); + if (Client.Instance.Networking.GetP2PSessionState(((SteamNetworkConnection)client.connection).steamId.ID, ref sessionState) && sessionState.Connecting == 0 && sessionState.ConnectionActive == 0) + { + client.connection.InvokeHandlerNoData(33); + StopClient(); + } + } + } + + protected override void PlatformAuth(ref ClientAuthData authData, NetworkConnection conn) + { + authData.platformId = new PlatformID(Client.Instance.SteamId); + authData.authTicket = Client.Instance.Auth.GetAuthSessionTicket().Data; + authData.entitlements = PlatformSystems.entitlementsSystem.BuildEntitlements(); + } + + protected override void StartClient(PlatformID serverID) + { + if (!NetworkServer.active) + { + NetworkManager.networkSceneName = ""; + } + string text = ""; + if (isNetworkActive) + { + text += "isNetworkActive "; + } + if (NetworkClient.active) + { + text += "NetworkClient.active "; + } + if (NetworkServer.active) + { + text += "NetworkClient.active "; + } + if (NetworkManagerSystem.isLoadingScene) + { + text += "isLoadingScene "; + } + if (text != "") + { + RoR2Application.onNextUpdate += delegate + { + }; + } + SteamNetworkConnection steamNetworkConnection = new SteamNetworkConnection(Client.Instance, serverID); + SteamNetworkClient steamNetworkClient = new SteamNetworkClient(steamNetworkConnection); + steamNetworkClient.Configure(base.connectionConfig, 1); + UseExternalClient(steamNetworkClient); + steamNetworkClient.Connect(); + Debug.LogFormat("Initiating connection to server {0}...", serverID.value); + if (!steamNetworkConnection.SendConnectionRequest()) + { + Debug.LogFormat("Failed to send connection request to server {0}.", serverID.value); + } + } + + public override bool IsConnectedToServer(PlatformID serverID) + { + if (client == null || !client.connection.isConnected || Client.Instance == null) + { + return false; + } + if (client.connection is SteamNetworkConnection steamNetworkConnection) + { + return steamNetworkConnection.steamId == serverID; + } + if (client.connection.address == "localServer") + { + return serverID == base.serverP2PId; + } + return false; + } + + public static bool IsMemberInSteamLobby(PlatformID steamId) + { + return Client.Instance.Lobby.UserIsInCurrentLobby(steamId.ID); + } + + private static PlatformID GetSteamworksSteamId(BaseSteamworks steamworks) + { + if (steamworks is Client client) + { + return new PlatformID(client.SteamId); + } + if (steamworks is Server server) + { + return new PlatformID(server.SteamId); + } + return PlatformID.nil; + } + + protected void InitP2P() + { + Facepunch.Steamworks.Networking networking = Server.Instance?.Networking; + Facepunch.Steamworks.Networking networking2 = Client.Instance?.Networking; + if (networking != null) + { + networking.OnIncomingConnection = OnSteamServerP2PIncomingConnection; + networking.OnConnectionFailed = OnSteamServerP2PConnectionFailed; + networking.OnP2PData = OnSteamServerP2PData; + for (int i = 0; i < base.connectionConfig.ChannelCount; i++) + { + networking.SetListenChannel(i, Listen: true); + } + } + if (networking2 != null) + { + networking2.OnIncomingConnection = OnSteamClientP2PIncomingConnection; + networking2.OnConnectionFailed = OnSteamClientP2PConnectionFailed; + networking2.OnP2PData = OnSteamClientP2PData; + for (int j = 0; j < base.connectionConfig.ChannelCount; j++) + { + networking2.SetListenChannel(j, Listen: true); + } + } + clientSteamworks = Client.Instance; + serverSteamworks = null; + if (NetworkServer.active) + { + serverSteamworks = (BaseSteamworks)(((object)(cvSteamP2PUseSteamServer.value ? Server.Instance : null)) ?? ((object)Client.Instance)); + } + base.clientP2PId = GetSteamworksSteamId(clientSteamworks); + base.serverP2PId = GetSteamworksSteamId(serverSteamworks); + } + + private bool OnSteamServerP2PIncomingConnection(ulong senderSteamId) + { + return OnIncomingP2PConnection(Server.Instance, new PlatformID(senderSteamId)); + } + + private void OnSteamServerP2PConnectionFailed(ulong senderSteamId, Facepunch.Steamworks.Networking.SessionError sessionError) + { + OnP2PConnectionFailed(Server.Instance, new PlatformID(senderSteamId), sessionError); + } + + private void OnSteamServerP2PData(ulong senderSteamId, byte[] data, int dataLength, int channel) + { + OnP2PData(Server.Instance, new PlatformID(senderSteamId), data, dataLength, channel); + } + + private bool OnSteamClientP2PIncomingConnection(ulong senderSteamId) + { + return OnIncomingP2PConnection(Client.Instance, new PlatformID(senderSteamId)); + } + + private void OnSteamClientP2PConnectionFailed(ulong senderSteamId, Facepunch.Steamworks.Networking.SessionError sessionError) + { + OnP2PConnectionFailed(Client.Instance, new PlatformID(senderSteamId), sessionError); + } + + private void OnSteamClientP2PData(ulong senderSteamId, byte[] data, int dataLength, int channel) + { + OnP2PData(Client.Instance, new PlatformID(senderSteamId), data, dataLength, channel); + } + + private bool OnIncomingP2PConnection(BaseSteamworks receiver, PlatformID senderSteamId) + { + bool flag = false; + if (receiver == serverSteamworks) + { + if (NetworkServer.active) + { + flag = !NetworkServer.dontListen && !steamIdBanList.Contains(senderSteamId) && !IsServerAtMaxConnections(); + } + else if (client is SteamNetworkClient && ((SteamNetworkClient)client).steamConnection.steamId == senderSteamId) + { + flag = true; + } + } + Debug.LogFormat("Incoming Steamworks connection from Steam ID {0}: {1}", senderSteamId, flag ? "accepted" : "rejected"); + if (flag) + { + CreateServerP2PConnectionWithPeer(receiver, senderSteamId); + } + return flag; + } + + private void OnP2PConnectionFailed(BaseSteamworks receiver, PlatformID senderSteamId, Facepunch.Steamworks.Networking.SessionError sessionError) + { + Debug.LogFormat("NetworkManagerSystem.OnClientP2PConnectionFailed steamId={0} sessionError={1}", senderSteamId, sessionError); + SteamNetworkConnection steamNetworkConnection = SteamNetworkConnection.Find(receiver, senderSteamId); + if (steamNetworkConnection != null) + { + if (client != null && client.connection == steamNetworkConnection) + { + steamNetworkConnection.InvokeHandlerNoData(33); + steamNetworkConnection.Disconnect(); + steamNetworkConnection.Dispose(); + } + if (NetworkServer.active && NetworkServer.connections.IndexOf(steamNetworkConnection) != -1) + { + ServerHandleClientDisconnect(steamNetworkConnection); + } + } + } + + private void OnP2PData(BaseSteamworks receiver, PlatformID senderSteamId, byte[] data, int dataLength, int channel) + { + if (SteamNetworkConnection.cvNetP2PDebugTransport.value) + { + Debug.LogFormat("Received packet from {0} dataLength={1} channel={2}", senderSteamId, dataLength, channel); + } + SteamNetworkConnection steamNetworkConnection = SteamNetworkConnection.Find(receiver, senderSteamId); + if (steamNetworkConnection != null) + { + steamNetworkConnection.TransportReceive(data, dataLength, 0); + return; + } + Debug.LogFormat("Rejecting data from sender: Not associated with a registered connection. steamid={0} dataLength={1}", senderSteamId, data); + } + + public void CreateServerP2PConnectionWithPeer(BaseSteamworks steamworks, PlatformID peer) + { + SteamNetworkConnection steamNetworkConnection = new SteamNetworkConnection(steamworks, peer); + steamNetworkConnection.ForceInitialize(NetworkServer.hostTopology); + int num = -1; + ReadOnlyCollection connections = NetworkServer.connections; + for (int i = 1; i < connections.Count; i++) + { + if (connections[i] == null) + { + num = i; + break; + } + } + if (num == -1) + { + num = connections.Count; + } + steamNetworkConnection.connectionId = num; + NetworkServer.AddExternalConnection(steamNetworkConnection); + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(32); + networkWriter.FinishMessage(); + steamNetworkConnection.SendWriter(networkWriter, QosChannelIndex.defaultReliable.intVal); + } + + protected override void PlatformClientSetPlayers(ConCommandArgs args) + { + if (client != null && client.connection != null) + { + ClientSetPlayers(client.connection); + } + } + + protected override void PlatformConnectP2P(ConCommandArgs args) + { + CheckSteamworks(); + PlatformID argPlatformID = args.GetArgPlatformID(0); + if (Client.Instance.Lobby.IsValid && !PlatformSystems.lobbyManager.ownsLobby && argPlatformID != PlatformSystems.lobbyManager.newestLobbyData.serverId) + { + Debug.LogFormat("Cannot connect to server {0}: Server is not the one specified by the current steam lobby.", argPlatformID); + } + else if (!(base.clientP2PId == argPlatformID)) + { + NetworkManagerSystem.singleton.desiredHost = new HostDescription(argPlatformID, HostDescription.HostType.Steam); + } + } + + protected override void PlatformDisconnect(ConCommandArgs args) + { + NetworkManagerSystem.singleton.desiredHost = HostDescription.none; + } + + protected override void PlatformConnect(ConCommandArgs args) + { + AddressPortPair argAddressPortPair = args.GetArgAddressPortPair(0); + if ((bool)NetworkManagerSystem.singleton) + { + NetworkManagerSystem.EnsureNetworkManagerNotBusy(); + Debug.LogFormat("Parsed address={0} port={1}. Setting desired host.", argAddressPortPair.address, argAddressPortPair.port); + NetworkManagerSystem.singleton.desiredHost = new HostDescription(argAddressPortPair); + } + } + + protected override void PlatformHost(ConCommandArgs args) + { + if (!NetworkManagerSystem.singleton) + { + return; + } + bool argBool = args.GetArgBool(0); + if (PlatformSystems.lobbyManager.isInLobby && !PlatformSystems.lobbyManager.ownsLobby) + { + return; + } + bool flag = false; + if (NetworkServer.active) + { + flag = true; + } + if (!flag) + { + int maxPlayers = SvMaxPlayersConVar.instance.intValue; + if (PlatformSystems.lobbyManager.isInLobby) + { + maxPlayers = PlatformSystems.lobbyManager.newestLobbyData.totalMaxPlayers; + } + NetworkManagerSystem.singleton.desiredHost = new HostDescription(new HostDescription.HostingParameters + { + listen = argBool, + maxPlayers = maxPlayers + }); + } + } + + protected override void PlatformGetP2PSessionState(ConCommandArgs args) + { + CheckSteamworks(); + PlatformID argPlatformID = args.GetArgPlatformID(0); + if ((bool)NetworkManagerSystem.singleton) + { + Facepunch.Steamworks.Networking.P2PSessionState sessionState = default(Facepunch.Steamworks.Networking.P2PSessionState); + if (Client.Instance.Networking.GetP2PSessionState(argPlatformID.ID, ref sessionState)) + { + Debug.LogFormat("ConnectionActive={0}\nConnecting={1}\nP2PSessionError={2}\nUsingRelay={3}\nBytesQueuedForSend={4}\nPacketsQueuedForSend={5}\nRemoteIP={6}\nRemotePort={7}", sessionState.ConnectionActive, sessionState.Connecting, sessionState.P2PSessionError, sessionState.UsingRelay, sessionState.BytesQueuedForSend, sessionState.PacketsQueuedForSend, sessionState.RemoteIP, sessionState.RemotePort); + } + else + { + Debug.LogFormat("Could not get p2p session info for steamId={0}", argPlatformID); + } + } + } + + protected override void PlatformKick(ConCommandArgs args) + { + CheckSteamworks(); + PlatformID argPlatformID = args.GetArgPlatformID(0); + NetworkConnection networkConnection = NetworkManagerSystem.singleton.GetClient(argPlatformID); + if (networkConnection != null) + { + NetworkManagerSystem.singleton.ServerKickClient(networkConnection, new SimpleLocalizedKickReason("KICK_REASON_KICK")); + } + } + + protected override void PlatformBan(ConCommandArgs args) + { + CheckSteamworks(); + PlatformID argPlatformID = args.GetArgPlatformID(0); + NetworkConnection networkConnection = NetworkManagerSystem.singleton.GetClient(argPlatformID); + if (networkConnection != null) + { + NetworkManagerSystem.singleton.ServerBanClient(networkConnection); + NetworkManagerSystem.singleton.ServerKickClient(networkConnection, new SimpleLocalizedKickReason("KICK_REASON_BAN")); + } + } + + public static void CheckSteamworks() + { + if (Client.Instance == null) + { + throw new ConCommandException("Steamworks not available."); + } + } + + public override void CreateLocalLobby() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkMessageHandlerAttribute.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkMessageHandlerAttribute.cs new file mode 100644 index 0000000..5e95445 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkMessageHandlerAttribute.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using HG.Reflection; +using JetBrains.Annotations; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +[MeansImplicitUse] +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] +public class NetworkMessageHandlerAttribute : HG.Reflection.SearchableAttribute +{ + public short msgType; + + public bool server; + + public bool client; + + private NetworkMessageDelegate messageHandler; + + private static List clientMessageHandlers = new List(); + + private static List serverMessageHandlers = new List(); + + [InitDuringStartup] + private static void CollectHandlers() + { + clientMessageHandlers.Clear(); + serverMessageHandlers.Clear(); + HashSet hashSet = new HashSet(); + foreach (NetworkMessageHandlerAttribute instance in HG.Reflection.SearchableAttribute.GetInstances()) + { + MethodInfo methodInfo = instance.target as MethodInfo; + if (methodInfo == null || !methodInfo.IsStatic) + { + continue; + } + instance.messageHandler = (NetworkMessageDelegate)Delegate.CreateDelegate(typeof(NetworkMessageDelegate), methodInfo); + if (instance.messageHandler != null) + { + if (instance.client) + { + clientMessageHandlers.Add(instance); + hashSet.Add(instance.msgType); + } + if (instance.server) + { + serverMessageHandlers.Add(instance); + hashSet.Add(instance.msgType); + } + } + if (instance.messageHandler == null) + { + Debug.LogWarningFormat("Could not register message handler for {0}. The function signature is likely incorrect.", methodInfo.Name); + } + if (!instance.client && !instance.server) + { + Debug.LogWarningFormat("Could not register message handler for {0}. It is marked as neither server nor client.", methodInfo.Name); + } + } + for (short num = 48; num < 80; num++) + { + if (!hashSet.Contains(num)) + { + Debug.LogWarningFormat("Network message MsgType.Highest + {0} is unregistered.", num - 47); + } + } + } + + public static void RegisterServerMessages() + { + foreach (NetworkMessageHandlerAttribute serverMessageHandler in serverMessageHandlers) + { + NetworkServer.RegisterHandler(serverMessageHandler.msgType, serverMessageHandler.messageHandler); + } + } + + public static void RegisterClientMessages(NetworkClient client) + { + foreach (NetworkMessageHandlerAttribute clientMessageHandler in clientMessageHandlers) + { + client.RegisterHandler(clientMessageHandler.msgType, clientMessageHandler.messageHandler); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkedViewAngles.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkedViewAngles.cs new file mode 100644 index 0000000..b35e309 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/NetworkedViewAngles.cs @@ -0,0 +1,148 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class NetworkedViewAngles : NetworkBehaviour +{ + public PitchYawPair viewAngles; + + private PitchYawPair networkDesiredViewAngles; + + private PitchYawPair velocity; + + private NetworkIdentity networkIdentity; + + public float sendRate = 0.05f; + + public float bufferMultiplier = 3f; + + public float maxSmoothVelocity = 1440f; + + private float sendTimer; + + private static int kCmdCmdUpdateViewAngles; + + public bool hasEffectiveAuthority { get; private set; } + + private void Awake() + { + networkIdentity = GetComponent(); + } + + private void Update() + { + hasEffectiveAuthority = Util.HasEffectiveAuthority(networkIdentity); + if (hasEffectiveAuthority) + { + networkDesiredViewAngles = viewAngles; + } + else + { + viewAngles = PitchYawPair.SmoothDamp(viewAngles, networkDesiredViewAngles, ref velocity, GetNetworkSendInterval() * bufferMultiplier, maxSmoothVelocity); + } + } + + public override float GetNetworkSendInterval() + { + return sendRate; + } + + private void FixedUpdate() + { + if (NetworkServer.active) + { + SetDirtyBit(1u); + } + hasEffectiveAuthority = Util.HasEffectiveAuthority(networkIdentity); + if (!hasEffectiveAuthority) + { + return; + } + networkDesiredViewAngles = viewAngles; + if (!NetworkServer.active) + { + sendTimer -= Time.deltaTime; + if (sendTimer <= 0f) + { + CallCmdUpdateViewAngles(viewAngles.pitch, viewAngles.yaw); + sendTimer = GetNetworkSendInterval(); + } + } + } + + [Command(channel = 5)] + public void CmdUpdateViewAngles(float pitch, float yaw) + { + networkDesiredViewAngles = new PitchYawPair(pitch, yaw); + } + + public override bool OnSerialize(NetworkWriter writer, bool initialState) + { + writer.Write(networkDesiredViewAngles); + return true; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + PitchYawPair pitchYawPair = reader.ReadPitchYawPair(); + if (!hasEffectiveAuthority) + { + networkDesiredViewAngles = pitchYawPair; + if (initialState) + { + viewAngles = pitchYawPair; + velocity = PitchYawPair.zero; + } + } + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdUpdateViewAngles(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdUpdateViewAngles called on client."); + } + else + { + ((NetworkedViewAngles)obj).CmdUpdateViewAngles(reader.ReadSingle(), reader.ReadSingle()); + } + } + + public void CallCmdUpdateViewAngles(float pitch, float yaw) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdUpdateViewAngles called on server."); + return; + } + if (base.isServer) + { + CmdUpdateViewAngles(pitch, yaw); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdUpdateViewAngles); + networkWriter.Write(GetComponent().netId); + networkWriter.Write(pitch); + networkWriter.Write(yaw); + SendCommandInternal(networkWriter, 5, "CmdUpdateViewAngles"); + } + + static NetworkedViewAngles() + { + kCmdCmdUpdateViewAngles = -1684781536; + NetworkBehaviour.RegisterCommandDelegate(typeof(NetworkedViewAngles), kCmdCmdUpdateViewAngles, InvokeCmdCmdUpdateViewAngles); + NetworkCRC.RegisterBehaviour("NetworkedViewAngles", 0); + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/QosChannelIndex.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/QosChannelIndex.cs new file mode 100644 index 0000000..9be72f8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/QosChannelIndex.cs @@ -0,0 +1,48 @@ +namespace RoR2.Networking; + +public struct QosChannelIndex +{ + public int intVal; + + public static QosChannelIndex defaultReliable = new QosChannelIndex + { + intVal = 0 + }; + + public static QosChannelIndex defaultUnreliable = new QosChannelIndex + { + intVal = 1 + }; + + public static QosChannelIndex characterTransformUnreliable = new QosChannelIndex + { + intVal = 2 + }; + + public static QosChannelIndex time = new QosChannelIndex + { + intVal = 3 + }; + + public static QosChannelIndex chat = new QosChannelIndex + { + intVal = 4 + }; + + public const int viewAnglesChannel = 5; + + public static QosChannelIndex viewAngles = new QosChannelIndex + { + intVal = 5 + }; + + public static QosChannelIndex ping = new QosChannelIndex + { + intVal = 6 + }; + + public static QosChannelIndex effects = new QosChannelIndex + { + intVal = 7 + }; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/RttManager.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/RttManager.cs new file mode 100644 index 0000000..444eace --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/RttManager.cs @@ -0,0 +1,196 @@ +using System; +using HG; +using RoR2.ConVar; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public static class RttManager +{ + private struct ConnectionRttInfo + { + public readonly NetworkConnection connection; + + public float newestRttInSeconds; + + public uint newestRttInMilliseconds; + + public float frameSmoothedRtt; + + public float frameVelocity; + + public float fixedSmoothedRtt; + + public float fixedVelocity; + + public ConnectionRttInfo(NetworkConnection connection) + { + this.connection = connection; + newestRttInMilliseconds = 0u; + newestRttInSeconds = 0f; + frameSmoothedRtt = 0f; + frameVelocity = 0f; + fixedSmoothedRtt = 0f; + fixedVelocity = 0f; + } + } + + private class PingMessage : MessageBase + { + public uint timeStampMs; + + public override void Serialize(NetworkWriter writer) + { + writer.WritePackedUInt32(timeStampMs); + } + + public override void Deserialize(NetworkReader reader) + { + timeStampMs = reader.ReadPackedUInt32(); + } + } + + private static ConnectionRttInfo[] entries = Array.Empty(); + + private static readonly FloatConVar cvRttSmoothDuration = new FloatConVar("net_rtt_smooth_duration", ConVarFlags.None, "0.1", "The smoothing duration for round-trip time values."); + + public static float GetConnectionRTT(NetworkConnection connection) + { + if (FindConnectionIndex(connection, out var entryIndex)) + { + return entries[entryIndex].newestRttInSeconds; + } + return 0f; + } + + public static uint GetConnectionRTTInMilliseconds(NetworkConnection connection) + { + if (FindConnectionIndex(connection, out var entryIndex)) + { + return entries[entryIndex].newestRttInMilliseconds; + } + return 0u; + } + + public static float GetConnectionFrameSmoothedRtt(NetworkConnection connection) + { + if (FindConnectionIndex(connection, out var entryIndex)) + { + return entries[entryIndex].frameSmoothedRtt; + } + return 0f; + } + + public static float GetConnectionFixedSmoothedRtt(NetworkConnection connection) + { + if (FindConnectionIndex(connection, out var entryIndex)) + { + return entries[entryIndex].fixedSmoothedRtt; + } + return 0f; + } + + private static void OnConnectionDiscovered(NetworkConnection connection) + { + ConnectionRttInfo value = new ConnectionRttInfo(connection); + ArrayUtils.ArrayAppend(ref entries, in value); + } + + private static void OnConnectionLost(NetworkConnection connection) + { + if (FindConnectionIndex(connection, out var entryIndex)) + { + ArrayUtils.ArrayRemoveAtAndResize(ref entries, entryIndex); + } + } + + private static bool FindConnectionIndex(NetworkConnection connection, out int entryIndex) + { + ConnectionRttInfo[] array = entries; + for (int i = 0; i < array.Length; i++) + { + if (array[i].connection == connection) + { + entryIndex = i; + return true; + } + } + entryIndex = -1; + return false; + } + + private static void UpdateFilteredRtt(float deltaTime, float targetValue, ref float currentValue, ref float velocity) + { + if (currentValue == 0f) + { + currentValue = targetValue; + velocity = 0f; + } + else + { + currentValue = Mathf.SmoothDamp(currentValue, targetValue, ref velocity, cvRttSmoothDuration.value, 100f, deltaTime); + } + } + + [RuntimeInitializeOnLoadMethod] + private static void Init() + { + NetworkManagerSystem.onClientConnectGlobal += OnConnectionDiscovered; + NetworkManagerSystem.onClientDisconnectGlobal += OnConnectionLost; + NetworkManagerSystem.onServerConnectGlobal += OnConnectionDiscovered; + NetworkManagerSystem.onServerDisconnectGlobal += OnConnectionLost; + RoR2Application.onUpdate += Update; + RoR2Application.onFixedUpdate += FixedUpdate; + } + + private static void Update() + { + float deltaTime = Time.deltaTime; + ConnectionRttInfo[] array = entries; + for (int i = 0; i < array.Length; i++) + { + ref ConnectionRttInfo reference = ref array[i]; + UpdateFilteredRtt(deltaTime, reference.newestRttInSeconds, ref reference.frameSmoothedRtt, ref reference.frameVelocity); + } + } + + private static void FixedUpdate() + { + float fixedDeltaTime = Time.fixedDeltaTime; + ConnectionRttInfo[] array = entries; + for (int i = 0; i < array.Length; i++) + { + ref ConnectionRttInfo reference = ref array[i]; + UpdateFilteredRtt(fixedDeltaTime, reference.newestRttInSeconds, ref reference.fixedSmoothedRtt, ref reference.fixedVelocity); + } + } + + [NetworkMessageHandler(msgType = 65, client = true, server = true)] + private static void HandlePing(NetworkMessage netMsg) + { + NetworkReader reader = netMsg.reader; + netMsg.conn.SendByChannel(66, reader.ReadMessage(), netMsg.channelId); + } + + [NetworkMessageHandler(msgType = 66, client = true, server = true)] + private static void HandlePingResponse(NetworkMessage netMsg) + { + uint timeStampMs = netMsg.reader.ReadMessage().timeStampMs; + uint num = (uint)(int)RoR2Application.stopwatch.ElapsedMilliseconds - timeStampMs; + if (FindConnectionIndex(netMsg.conn, out var entryIndex)) + { + ref ConnectionRttInfo reference = ref entries[entryIndex]; + reference.newestRttInMilliseconds = num; + reference.newestRttInSeconds = (float)num * 0.001f; + } + } + + public static void Ping(NetworkConnection conn, int channelId) + { + conn.SendByChannel(65, new PingMessage + { + timeStampMs = (uint)RoR2Application.stopwatch.ElapsedMilliseconds + }, channelId); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/ServerAuthManager.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/ServerAuthManager.cs new file mode 100644 index 0000000..249c41d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/ServerAuthManager.cs @@ -0,0 +1,155 @@ +using System; +using HG; +using JetBrains.Annotations; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public static class ServerAuthManager +{ + public struct KeyValue + { + public readonly NetworkConnection conn; + + public readonly ClientAuthData authData; + + public KeyValue(NetworkConnection conn, ClientAuthData authData) + { + this.conn = conn; + this.authData = authData; + } + } + + private static readonly int initialSize = 16; + + public static KeyValue[] instances = new KeyValue[initialSize]; + + private static int instanceCount = 0; + + public static event Action onAuthDataReceivedFromClient; + + public static event Action onAuthExpired; + + [RuntimeInitializeOnLoadMethod] + private static void Init() + { + NetworkManagerSystem.onServerConnectGlobal += OnConnectionDiscovered; + NetworkManagerSystem.onServerDisconnectGlobal += OnConnectionLost; + } + + private static void OnConnectionDiscovered(NetworkConnection conn) + { + } + + private static void OnConnectionLost(NetworkConnection conn) + { + for (int i = 0; i < instanceCount; i++) + { + if (instances[i].conn == conn) + { + ServerAuthManager.onAuthExpired?.Invoke(conn, instances[i].authData); + ArrayUtils.ArrayRemoveAt(instances, ref instanceCount, i); + break; + } + } + } + + public static ClientAuthData FindAuthData(NetworkConnection conn) + { + for (int i = 0; i < instanceCount; i++) + { + if (instances[i].conn == conn) + { + return instances[i].authData; + } + } + return null; + } + + public static NetworkConnection FindConnectionForSteamID(PlatformID steamId) + { + for (int i = 0; i < instanceCount; i++) + { + if (instances[i].authData.platformId == steamId) + { + return instances[i].conn; + } + } + return null; + } + + [NetworkMessageHandler(client = false, server = true, msgType = 74)] + private static void HandleSetClientAuth(NetworkMessage netMsg) + { + if (netMsg.conn == null) + { + Debug.LogWarning("ServerAuthManager.HandleSetClientAuth(): Connection is null."); + } + else + { + if (FindAuthData(netMsg.conn) != null) + { + return; + } + bool flag = Util.ConnectionIsLocal(netMsg.conn); + NetworkManagerSystem.BaseKickReason baseKickReason = null; + try + { + ClientAuthData clientAuthData = netMsg.ReadMessage(); + NetworkConnection networkConnection = FindConnectionForSteamID(clientAuthData.platformId); + if (networkConnection != null) + { + Debug.LogFormat("SteamID {0} is already claimed by connection [{1}]. Connection [{2}] rejected.", clientAuthData.platformId, networkConnection, netMsg.conn); + PlatformSystems.networkManager.ServerKickClient(netMsg.conn, new NetworkManagerSystem.SimpleLocalizedKickReason("KICK_REASON_ACCOUNT_ALREADY_ON_SERVER")); + return; + } + KeyValue value = new KeyValue(netMsg.conn, clientAuthData); + ArrayUtils.ArrayAppend(ref instances, ref instanceCount, in value); + string value2 = NetworkManagerSystem.SvPasswordConVar.instance.value; + if (!flag && value2.Length != 0 && !(clientAuthData.password == value2)) + { + Debug.LogFormat("Rejecting connection from [{0}]: {1}", netMsg.conn, "Bad password."); + baseKickReason = new NetworkManagerSystem.SimpleLocalizedKickReason("KICK_REASON_BADPASSWORD"); + } + string version = clientAuthData.version; + string buildId = RoR2Application.GetBuildId(); + if (!string.Equals(version, buildId, StringComparison.OrdinalIgnoreCase)) + { + Debug.LogFormat("Rejecting connection from [{0}]: {1}", netMsg.conn, "Bad version."); + baseKickReason = new NetworkManagerSystem.SimpleLocalizedKickReason("KICK_REASON_BADVERSION", version, buildId); + } + string modHash = clientAuthData.modHash; + string networkModHash = NetworkModCompatibilityHelper.networkModHash; + if (!string.Equals(modHash, networkModHash, StringComparison.OrdinalIgnoreCase)) + { + Debug.LogFormat("Rejecting connection from [{0}]: {1}", netMsg.conn, "Mod mismatch."); + baseKickReason = new NetworkManagerSystem.ModMismatchKickReason(NetworkModCompatibilityHelper.networkModList); + } + ServerAuthManager.onAuthDataReceivedFromClient?.Invoke(value.conn, value.authData); + } + catch + { + Debug.LogFormat("Rejecting connection from [{0}]: {1}", netMsg.conn, "Malformed auth data."); + baseKickReason = new NetworkManagerSystem.SimpleLocalizedKickReason("KICK_REASON_MALFORMED_AUTH_DATA"); + } + if (baseKickReason != null) + { + PlatformSystems.networkManager.ServerKickClient(netMsg.conn, baseKickReason); + } + } + } + + [CanBeNull] + public static ClientAuthData GetClientAuthData(NetworkConnection networkConnection) + { + for (int i = 0; i < instances.Length; i++) + { + if (instances[i].conn == networkConnection) + { + return instances[i].authData; + } + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/SteamLobbyFinder.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/SteamLobbyFinder.cs new file mode 100644 index 0000000..ca170c4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/SteamLobbyFinder.cs @@ -0,0 +1,447 @@ +using System; +using System.Collections.Generic; +using EntityStates; +using Facepunch.Steamworks; +using UnityEngine; + +namespace RoR2.Networking; + +public class SteamLobbyFinder : MonoBehaviour +{ + private class LobbyStateBase : BaseState + { + protected SteamLobbyFinder lobbyFinder; + + public override void OnEnter() + { + base.OnEnter(); + lobbyFinder = GetComponent(); + LobbyManager lobbyManager = PlatformSystems.lobbyManager; + lobbyManager.onLobbyOwnershipGained = (Action)Delegate.Combine(lobbyManager.onLobbyOwnershipGained, new Action(OnLobbyOwnershipGained)); + LobbyManager lobbyManager2 = PlatformSystems.lobbyManager; + lobbyManager2.onLobbyOwnershipLost = (Action)Delegate.Combine(lobbyManager2.onLobbyOwnershipLost, new Action(OnLobbyOwnershipLost)); + } + + public override void OnExit() + { + LobbyManager lobbyManager = PlatformSystems.lobbyManager; + lobbyManager.onLobbyOwnershipGained = (Action)Delegate.Remove(lobbyManager.onLobbyOwnershipGained, new Action(OnLobbyOwnershipGained)); + LobbyManager lobbyManager2 = PlatformSystems.lobbyManager; + lobbyManager2.onLobbyOwnershipLost = (Action)Delegate.Remove(lobbyManager2.onLobbyOwnershipLost, new Action(OnLobbyOwnershipLost)); + base.OnExit(); + } + + public virtual void OnLobbiesUpdated() + { + } + + private void OnLobbyOwnershipGained() + { + outer.SetNextState(new LobbyStateStart()); + } + + private void OnLobbyOwnershipLost() + { + outer.SetNextState(new LobbyStateNonLeader()); + } + } + + private class LobbyStateNonLeader : LobbyStateBase + { + public override void Update() + { + base.Update(); + if (PlatformSystems.lobbyManager.ownsLobby) + { + if (PlatformSystems.lobbyManager.hasMinimumPlayerCount) + { + outer.SetNextState(new LobbyStateMultiSearch()); + } + else + { + outer.SetNextState(new LobbyStateSingleSearch()); + } + } + } + } + + private class LobbyStateStart : LobbyStateBase + { + public override void Update() + { + base.Update(); + if (lobbyFinder.startDelayDuration <= base.age) + { + outer.SetNextState(PlatformSystems.lobbyManager.hasMinimumPlayerCount ? ((LobbyStateBase)new LobbyStateMultiSearch()) : ((LobbyStateBase)new LobbyStateSingleSearch())); + } + } + } + + private class LobbyStateSingleSearch : LobbyStateBase + { + public override void OnEnter() + { + base.OnEnter(); + (PlatformSystems.lobbyManager as SteamworksLobbyManager).SetLobbyQuickPlayCutoffTimeIfOwner(null); + } + + public override void Update() + { + base.Update(); + if (PlatformSystems.lobbyManager.hasMinimumPlayerCount) + { + outer.SetNextState(new LobbyStateMultiSearch()); + } + else if (lobbyFinder.refreshTimer <= 0f) + { + if (base.age >= lobbyFinder.joinOnlyDuration && steamClient.Lobby.LobbyType != Lobby.Type.Public) + { + Debug.LogFormat("Unable to find joinable lobby after {0} seconds. Setting lobby to public.", lobbyFinder.age); + steamClient.Lobby.LobbyType = Lobby.Type.Public; + } + lobbyFinder.refreshTimer = lobbyFinder.refreshInterval; + lobbyFinder.RequestLobbyListRefresh(); + } + } + + public override void OnLobbiesUpdated() + { + base.OnLobbiesUpdated(); + if (!steamClient.IsValid) + { + return; + } + List lobbies = steamClient.LobbyList.Lobbies; + List list = new List(); + ulong currentLobby = steamClient.Lobby.CurrentLobby; + bool isValid = steamClient.Lobby.IsValid; + int currentLobbySize = (isValid ? GetCurrentLobbyRealPlayerCount() : LocalUserManager.readOnlyLocalUsersList.Count); + if (PlatformSystems.lobbyManager.ownsLobby || !isValid) + { + for (int i = 0; i < lobbies.Count; i++) + { + if ((!isValid || lobbies[i].LobbyID < currentLobby) && CanJoinLobby(currentLobbySize, lobbies[i])) + { + list.Add(lobbies[i]); + } + } + if (list.Count > 0) + { + PlatformID join = new PlatformID(list[0].LobbyID); + PlatformSystems.lobbyManager.JoinLobby(join); + } + } + Debug.LogFormat("Found {0} lobbies, {1} joinable.", lobbies.Count, list.Count); + } + } + + private class LobbyStateMultiSearch : LobbyStateBase + { + public override void OnEnter() + { + base.OnEnter(); + steamClient.Lobby.LobbyType = Lobby.Type.Public; + TimeSpan timeSpan = Util.UnixTimeStampToDateTimeUtc(steamClient.Utils.GetServerRealTime()) + TimeSpan.FromSeconds(lobbyFinder.waitForFullDuration) - Util.dateZero; + (PlatformSystems.lobbyManager as SteamworksLobbyManager).SetLobbyQuickPlayCutoffTimeIfOwner((uint)timeSpan.TotalSeconds); + } + + public override void OnExit() + { + (PlatformSystems.lobbyManager as SteamworksLobbyManager).SetLobbyQuickPlayCutoffTimeIfOwner(null); + base.OnExit(); + } + + public override void Update() + { + base.Update(); + if (!PlatformSystems.lobbyManager.hasMinimumPlayerCount) + { + outer.SetNextState(new LobbyStateSingleSearch()); + } + else if (lobbyFinder.waitForFullDuration <= base.age) + { + outer.SetNextState(new LobbyStateBeginGame()); + } + } + } + + private class LobbyStateBeginGame : LobbyStateBase + { + public override void OnEnter() + { + base.OnEnter(); + steamClient.Lobby.LobbyType = (Lobby.Type)PlatformSystems.lobbyManager.preferredLobbyType; + (PlatformSystems.lobbyManager as SteamworksLobbyManager).SetStartingIfOwner(startingState: true); + string arg = "ClassicRun"; + Console.instance.SubmitCmd(null, $"transition_command \"gamemode {arg}; host 1;\""); + } + } + + private float age; + + public float joinOnlyDuration = 5f; + + public float waitForFullDuration = 30f; + + public float startDelayDuration = 1f; + + public float refreshInterval = 2f; + + private float refreshTimer; + + private EntityStateMachine stateMachine; + + private static SteamLobbyFinder instance; + + private static bool _userRequestedQuickplayQueue; + + private static bool _lobbyIsInQuickplayQueue; + + private static Client steamClient => Client.Instance; + + public static bool userRequestedQuickplayQueue + { + get + { + return _userRequestedQuickplayQueue; + } + set + { + if (_userRequestedQuickplayQueue != value) + { + _userRequestedQuickplayQueue = value; + running = _lobbyIsInQuickplayQueue || _userRequestedQuickplayQueue; + } + } + } + + private static bool lobbyIsInQuickplayQueue + { + get + { + return _lobbyIsInQuickplayQueue; + } + set + { + if (_lobbyIsInQuickplayQueue != value) + { + _lobbyIsInQuickplayQueue = value; + running = _lobbyIsInQuickplayQueue || _userRequestedQuickplayQueue; + } + } + } + + public static bool running + { + get + { + return instance; + } + private set + { + if ((bool)instance != value) + { + if (value) + { + instance = new GameObject("SteamLobbyFinder", typeof(SteamLobbyFinder), typeof(SetDontDestroyOnLoad)).GetComponent(); + } + else + { + UnityEngine.Object.Destroy(instance.gameObject); + instance = null; + } + } + } + } + + private void Awake() + { + stateMachine = base.gameObject.AddComponent(); + stateMachine.initialStateType = new SerializableEntityStateType(typeof(LobbyStateStart)); + } + + private void OnDestroy() + { + UnityEngine.Object.Destroy(stateMachine); + } + + private void Update() + { + if (steamClient.Lobby.IsValid && !PlatformSystems.lobbyManager.ownsLobby) + { + if (stateMachine.state.GetType() != typeof(LobbyStateNonLeader)) + { + stateMachine.SetNextState(new LobbyStateNonLeader()); + } + } + else + { + refreshTimer -= Time.unscaledDeltaTime; + age += Time.unscaledDeltaTime; + } + } + + private void RequestLobbyListRefresh() + { + LobbyList.Filter filter = new LobbyList.Filter + { + StringFilters = + { + ["appid"] = TextSerialization.ToStringInvariant(steamClient.AppId), + ["build_id"] = RoR2Application.GetBuildId(), + ["qp"] = "1", + ["total_max_players"] = TextSerialization.ToStringInvariant(RoR2Application.maxPlayers) + } + }; + (PlatformSystems.lobbyManager as SteamworksLobbyManager).RequestLobbyList(this, filter, OnLobbyListReceived); + } + + private void OnLobbyListReceived(List newLobbies) + { + if ((bool)this) + { + (stateMachine.state as LobbyStateBase)?.OnLobbiesUpdated(); + } + } + + private static bool CanJoinLobby(int currentLobbySize, LobbyList.Lobby lobby) + { + return currentLobbySize + GetRealLobbyPlayerCount(lobby) <= lobby.MemberLimit; + } + + private static int GetRealLobbyPlayerCount(LobbyList.Lobby lobby) + { + string data = lobby.GetData("player_count"); + if (data != null && TextSerialization.TryParseInvariant(data, out int result)) + { + return result; + } + return steamClient.Lobby.MaxMembers; + } + + private static int GetCurrentLobbyRealPlayerCount() + { + return PlatformSystems.lobbyManager.newestLobbyData.totalPlayerCount; + } + + [ConCommand(commandName = "steam_quickplay_start")] + private static void CCSteamQuickplayStart(ConCommandArgs args) + { + NetworkManagerSystemSteam.CheckSteamworks(); + userRequestedQuickplayQueue = true; + (PlatformSystems.lobbyManager as SteamworksLobbyManager).SetLobbyQuickPlayQueuedIfOwner(quickplayQueuedState: true); + } + + [ConCommand(commandName = "steam_quickplay_stop")] + private static void CCSteamQuickplayStop(ConCommandArgs args) + { + NetworkManagerSystemSteam.CheckSteamworks(); + userRequestedQuickplayQueue = false; + PlatformSystems.lobbyManager.CreateLobby(); + } + + public static void Init() + { + LobbyManager lobbyManager = PlatformSystems.lobbyManager; + lobbyManager.onLobbyDataUpdated = (Action)Delegate.Combine(lobbyManager.onLobbyDataUpdated, new Action(OnLobbyDataUpdated)); + NetworkManagerSystem.onStartClientGlobal += delegate + { + (PlatformSystems.lobbyManager as SteamworksLobbyManager).SetLobbyQuickPlayQueuedIfOwner(quickplayQueuedState: false); + userRequestedQuickplayQueue = false; + }; + LobbyManager lobbyManager2 = PlatformSystems.lobbyManager; + lobbyManager2.onLobbyOwnershipGained = (Action)Delegate.Combine(lobbyManager2.onLobbyOwnershipGained, (Action)delegate + { + if (PlatformSystems.lobbyManager.newestLobbyData.quickplayQueued) + { + userRequestedQuickplayQueue = true; + } + }); + LobbyManager lobbyManager3 = PlatformSystems.lobbyManager; + lobbyManager3.onLobbyOwnershipLost = (Action)Delegate.Combine(lobbyManager3.onLobbyOwnershipLost, (Action)delegate + { + userRequestedQuickplayQueue = false; + }); + } + + private static void OnLobbyDataUpdated() + { + lobbyIsInQuickplayQueue = PlatformSystems.lobbyManager.newestLobbyData.quickplayQueued; + } + + public static string GetResolvedStateString() + { + if (!steamClient.Lobby.IsValid) + { + return Language.GetString("STEAM_LOBBY_STATUS_NOT_IN_LOBBY"); + } + bool flag = steamClient.Lobby.LobbyType == Lobby.Type.Public; + if ((bool)instance) + { + _ = instance.stateMachine.state is LobbyStateSingleSearch; + } + else + _ = 0; + _ = PlatformSystems.lobbyManager.newestLobbyData.totalPlayerCount; + _ = PlatformSystems.lobbyManager.newestLobbyData.totalMaxPlayers; + _ = PlatformSystems.lobbyManager.isFull; + string token = string.Empty; + object[] args = Array.Empty(); + if (NetworkManagerSystem.singleton.isHost || PlatformSystems.lobbyManager.state == LobbyManager.State.Hosting) + { + token = "STEAM_LOBBY_STATUS_STARTING_SERVER"; + } + else if (PlatformSystems.lobbyManager.newestLobbyData.starting) + { + token = "STEAM_LOBBY_STATUS_GAME_STARTING"; + } + else if (PlatformSystems.lobbyManager.newestLobbyData.shouldConnect) + { + token = "STEAM_LOBBY_STATUS_CONNECTING_TO_HOST"; + } + else if ((bool)instance && instance.stateMachine.state is LobbyStateStart) + { + token = "STEAM_LOBBY_STATUS_LAUNCHING_QUICKPLAY"; + } + else if (PlatformSystems.lobbyManager.isInLobby) + { + if (PlatformSystems.lobbyManager.newestLobbyData.quickplayQueued) + { + if (!flag) + { + token = "STEAM_LOBBY_STATUS_QUICKPLAY_SEARCHING_FOR_EXISTING_LOBBY"; + } + else + { + DateTime dateTime = Util.UnixTimeStampToDateTimeUtc(steamClient.Utils.GetServerRealTime()); + DateTime? quickplayCutoffTime = PlatformSystems.lobbyManager.newestLobbyData.quickplayCutoffTime; + if (!quickplayCutoffTime.HasValue) + { + token = "STEAM_LOBBY_STATUS_QUICKPLAY_WAITING_BELOW_MINIMUM_PLAYERS"; + args = new object[2] + { + PlatformSystems.lobbyManager.newestLobbyData.totalPlayerCount, + PlatformSystems.lobbyManager.newestLobbyData.totalMaxPlayers + }; + } + else + { + TimeSpan timeSpan = quickplayCutoffTime.Value - dateTime; + token = "STEAM_LOBBY_STATUS_QUICKPLAY_WAITING_ABOVE_MINIMUM_PLAYERS"; + args = new object[3] + { + PlatformSystems.lobbyManager.newestLobbyData.totalPlayerCount, + PlatformSystems.lobbyManager.newestLobbyData.totalMaxPlayers, + Math.Max(0.0, timeSpan.TotalSeconds) + }; + } + } + } + else + { + token = "STEAM_LOBBY_STATUS_OUT_OF_QUICKPLAY"; + } + } + return Language.GetStringFormatted(token, args); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/SteamNetworkClient.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/SteamNetworkClient.cs new file mode 100644 index 0000000..0491b39 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/SteamNetworkClient.cs @@ -0,0 +1,23 @@ +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class SteamNetworkClient : NetworkClient +{ + public SteamNetworkConnection steamConnection => (SteamNetworkConnection)base.connection; + + public string status => m_AsyncConnect.ToString(); + + public void Connect() + { + Connect("localhost", 0); + m_AsyncConnect = ConnectState.Connected; + base.connection.ForceInitialize(base.hostTopology); + } + + public SteamNetworkClient(NetworkConnection conn) + : base(conn) + { + SetNetworkConnectionClass(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/SteamNetworkConnection.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/SteamNetworkConnection.cs new file mode 100644 index 0000000..96b4231 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/SteamNetworkConnection.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using Facepunch.Steamworks; +using JetBrains.Annotations; +using RoR2.ConVar; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public class SteamNetworkConnection : NetworkConnection +{ + private BaseSteamworks steamworks; + + private Facepunch.Steamworks.Networking networking; + + private static List instancesList = new List(); + + public bool ignore; + + public uint rtt; + + public static BoolConVar cvNetP2PDebugTransport = new BoolConVar("net_p2p_debug_transport", ConVarFlags.None, "0", "Allows p2p transport information to print to the console."); + + private static BoolConVar cvNetP2PLogMessages = new BoolConVar("net_p2p_log_messages", ConVarFlags.None, "0", "Enables logging of network messages."); + + public PlatformID myId { get; private set; } + + public PlatformID steamId { get; private set; } + + public SteamNetworkConnection() + { + } + + public SteamNetworkConnection([NotNull] BaseSteamworks steamworks, PlatformID endpointId) + { + myId = new PlatformID((steamworks as Client)?.SteamId ?? (steamworks as Server)?.SteamId ?? 0); + steamId = endpointId; + this.steamworks = steamworks; + networking = steamworks.Networking; + networking.CloseSession(endpointId.ID); + instancesList.Add(this); + } + + public bool SendConnectionRequest() + { + return networking.SendP2PPacket(steamId.ID, null, 0); + } + + public override bool TransportSend(byte[] bytes, int numBytes, int channelId, out byte error) + { + if (ignore) + { + error = 0; + return true; + } + logNetworkMessages = cvNetP2PLogMessages.value; + if (steamId == myId) + { + TransportReceive(bytes, numBytes, channelId); + error = 0; + if (cvNetP2PDebugTransport.value) + { + Debug.LogFormat("SteamNetworkConnection.TransportSend steamId=self numBytes={1} channelId={2}", numBytes, channelId); + } + return true; + } + Facepunch.Steamworks.Networking.SendType eP2PSendType = Facepunch.Steamworks.Networking.SendType.Reliable; + QosType qOS = PlatformSystems.networkManager.connectionConfig.Channels[channelId].QOS; + if (qOS == QosType.Unreliable || qOS == QosType.UnreliableFragmented || qOS == QosType.UnreliableSequenced) + { + eP2PSendType = Facepunch.Steamworks.Networking.SendType.Unreliable; + } + if (networking.SendP2PPacket(steamId.ID, bytes, numBytes, eP2PSendType)) + { + error = 0; + if (cvNetP2PDebugTransport.value) + { + Debug.LogFormat("SteamNetworkConnection.TransportSend steamId={0} numBytes={1} channelId={2} error={3}", steamId.value, numBytes, channelId, error); + } + return true; + } + error = 1; + if (cvNetP2PDebugTransport.value) + { + Debug.LogFormat("SteamNetworkConnection.TransportSend steamId={0} numBytes={1} channelId={2} error={3}", steamId.value, numBytes, channelId, error); + } + return false; + } + + public override void TransportReceive(byte[] bytes, int numBytes, int channelId) + { + if (!ignore) + { + logNetworkMessages = cvNetP2PLogMessages.value; + base.TransportReceive(bytes, numBytes, channelId); + } + } + + protected override void Dispose(bool disposing) + { + instancesList.Remove(this); + if (networking != null && steamId.ID != 0L) + { + networking.CloseSession(steamId.ID); + steamId = PlatformID.nil; + } + base.Dispose(disposing); + } + + public static SteamNetworkConnection Find(BaseSteamworks owner, PlatformID endpoint) + { + for (int i = 0; i < instancesList.Count; i++) + { + SteamNetworkConnection steamNetworkConnection = instancesList[i]; + if (steamNetworkConnection.steamId == endpoint && owner == steamNetworkConnection.steamworks) + { + return steamNetworkConnection; + } + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/UNETExtensions.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/UNETExtensions.cs new file mode 100644 index 0000000..d68d9f1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/UNETExtensions.cs @@ -0,0 +1,12 @@ +using UnityEngine.Networking; + +namespace RoR2.Networking; + +public static class UNETExtensions +{ + public static void ForceInitialize(this NetworkConnection conn, HostTopology hostTopology) + { + int num = 0; + conn.Initialize("localhost", num, num, hostTopology); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Networking/UmsgType.cs b/ilspy_dump/ror2_csproj/RoR2.Networking/UmsgType.cs new file mode 100644 index 0000000..3858864 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Networking/UmsgType.cs @@ -0,0 +1,74 @@ +namespace RoR2.Networking; + +public class UmsgType +{ + public const short Lowest = 48; + + public const short SetEntityState = 48; + + public const short PlayerFireProjectile = 49; + + public const short ReleaseProjectilePredictionId = 50; + + public const short CharacterTransformUpdate = 51; + + public const short Effect = 52; + + public const short BulletDamage = 53; + + public const short UpdateTime = 54; + + public const short CreateExpEffect = 55; + + public const short ResetSkills = 56; + + public const short PickupItem = 57; + + public const short StatsUpdate = 58; + + public const short BroadcastChat = 59; + + public const short DamageDealt = 60; + + public const short Heal = 61; + + public const short ConstructTurret = 62; + + public const short AmmoPackPickup = 63; + + public const short Test = 64; + + public const short Ping = 65; + + public const short PingResponse = 66; + + public const short Kick = 67; + + public const short Teleport = 68; + + public const short SetJetpackJumpState = 69; + + public const short PreGameRuleVoteControllerSendClientVotes = 70; + + public const short OverlapAttackHits = 71; + + public const short EmitPointSound = 72; + + public const short EmitEntitySound = 73; + + public const short SetClientAuth = 74; + + public const short ReportBlastAttackDamage = 75; + + public const short NetworkUIPromptMessage = 76; + + public const short ReportMercFocusedAssaultHitReplaceMeLater = 77; + + public const short TransformPickup = 78; + + public const short Pause = 79; + + public const short TransmitWokDataToServer = 80; + + public const short Highest = 80; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/BeetleWardOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/BeetleWardOrb.cs new file mode 100644 index 0000000..ae1b822 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/BeetleWardOrb.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Orbs; + +public class BeetleWardOrb : Orb +{ + public float speed; + + public override void Begin() + { + base.duration = base.distanceToTarget / speed; + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/BeetleWardOrbEffect"), effectData, transmit: true); + } + + public override void OnArrival() + { + if ((bool)target) + { + GameObject gameObject = Object.Instantiate(OrbStorageUtility.Get("Prefabs/NetworkedObjects/BeetleWard"), target.transform.position, Quaternion.identity); + gameObject.GetComponent().teamIndex = target.teamIndex; + NetworkServer.Spawn(gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/BounceOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/BounceOrb.cs new file mode 100644 index 0000000..9557e69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/BounceOrb.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; +using HG; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Orbs; + +public class BounceOrb : Orb +{ + private const float speed = 70f; + + public float damageValue; + + public GameObject attacker; + + public TeamIndex teamIndex; + + public List bouncedObjects; + + public bool isCrit; + + public float scale; + + public ProcChainMask procChainMask; + + public float procCoefficient = 0.2f; + + public DamageColorIndex damageColorIndex; + + public override void Begin() + { + base.duration = base.distanceToTarget / 70f; + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/BounceOrbEffect"), effectData, transmit: true); + } + + public override void OnArrival() + { + if ((bool)target) + { + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + Vector3 position = target.transform.position; + GameObject gameObject = healthComponent.gameObject; + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = null; + damageInfo.force = (position - origin).normalized * -1000f; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = position; + damageInfo.damageColorIndex = damageColorIndex; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, gameObject); + } + } + } + + public static void SearchForTargets([NotNull] BullseyeSearch search, TeamIndex teamIndex, Vector3 position, float range, int maxTargets, [NotNull] List dest, [NotNull] List exclusions) + { + search.searchOrigin = position; + search.searchDirection = Vector3.zero; + search.teamMaskFilter = TeamMask.GetEnemyTeams(teamIndex); + search.filterByLoS = false; + search.sortMode = BullseyeSearch.SortMode.None; + search.maxDistanceFilter = range; + search.RefreshCandidates(); + List list = CollectionPool>.RentCollection(); + foreach (HurtBox result in search.GetResults()) + { + list.Add(result); + } + Util.ShuffleList(list); + int i = 0; + for (int count = list.Count; i < count; i++) + { + HurtBox hurtBox = list[i]; + if ((bool)hurtBox.healthComponent && !exclusions.Contains(hurtBox.healthComponent)) + { + if (exclusions.Count >= maxTargets) + { + break; + } + exclusions.Add(hurtBox.healthComponent); + dest.Add(hurtBox); + } + } + CollectionPool>.ReturnCollection(list); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/ChainGunOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/ChainGunOrb.cs new file mode 100644 index 0000000..bfcfc08 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/ChainGunOrb.cs @@ -0,0 +1,121 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace RoR2.Orbs; + +public class ChainGunOrb : GenericDamageOrb +{ + private GameObject orbEffectPrefab; + + public int bouncesRemaining; + + public float bounceRange = 20f; + + public float damageCoefficientPerBounce = 1f; + + public int targetsToFindPerBounce = 1; + + public bool canBounceOnSameTarget; + + private List bouncedObjects; + + private BullseyeSearch search; + + public ChainGunOrb(GameObject orbEffectObject) + { + orbEffectPrefab = orbEffectObject; + bouncedObjects = new List(); + } + + protected override GameObject GetOrbEffect() + { + return orbEffectPrefab; + } + + public override void OnArrival() + { + if (!target) + { + return; + } + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + damageInfo.damageType = damageType; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + } + if (bouncesRemaining <= 0) + { + return; + } + for (int i = 0; i < targetsToFindPerBounce; i++) + { + if (bouncedObjects != null) + { + if (canBounceOnSameTarget) + { + bouncedObjects.Clear(); + } + bouncedObjects.Add(target.healthComponent); + } + HurtBox hurtBox = PickNextTarget(target.transform.position); + if ((bool)hurtBox) + { + ChainGunOrb chainGunOrb = new ChainGunOrb(orbEffectPrefab); + chainGunOrb.search = search; + chainGunOrb.origin = target.transform.position; + chainGunOrb.target = hurtBox; + chainGunOrb.attacker = attacker; + chainGunOrb.teamIndex = teamIndex; + chainGunOrb.damageValue = damageValue * damageCoefficientPerBounce; + chainGunOrb.bouncesRemaining = bouncesRemaining - 1; + chainGunOrb.isCrit = isCrit; + chainGunOrb.bouncedObjects = bouncedObjects; + chainGunOrb.procChainMask = procChainMask; + chainGunOrb.procCoefficient = procCoefficient; + chainGunOrb.damageColorIndex = damageColorIndex; + chainGunOrb.damageCoefficientPerBounce = damageCoefficientPerBounce; + chainGunOrb.speed = speed; + chainGunOrb.bounceRange = bounceRange; + chainGunOrb.damageType = damageType; + OrbManager.instance.AddOrb(chainGunOrb); + } + } + } + + public HurtBox PickNextTarget(Vector3 position) + { + if (search == null) + { + search = new BullseyeSearch(); + } + search.searchOrigin = position; + search.searchDirection = Vector3.zero; + search.teamMaskFilter = TeamMask.allButNeutral; + search.teamMaskFilter.RemoveTeam(teamIndex); + search.filterByLoS = false; + search.sortMode = BullseyeSearch.SortMode.Distance; + search.maxDistanceFilter = bounceRange; + search.RefreshCandidates(); + HurtBox hurtBox = (from v in search.GetResults() + where !bouncedObjects.Contains(v.healthComponent) + select v).FirstOrDefault(); + if ((bool)hurtBox) + { + bouncedObjects.Add(hurtBox.healthComponent); + } + return hurtBox; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/DamageOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/DamageOrb.cs new file mode 100644 index 0000000..f1164e5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/DamageOrb.cs @@ -0,0 +1,86 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class DamageOrb : Orb +{ + public enum DamageOrbType + { + ClayGooOrb + } + + private float speed = 60f; + + public float damageValue; + + public GameObject attacker; + + public TeamIndex teamIndex; + + public bool isCrit; + + public ProcChainMask procChainMask; + + public float procCoefficient = 0.2f; + + public DamageColorIndex damageColorIndex; + + public DamageOrbType damageOrbType; + + private DamageTypeCombo orbDamageType = DamageType.Generic; + + public override void Begin() + { + GameObject effectPrefab = null; + if (damageOrbType == DamageOrbType.ClayGooOrb) + { + speed = 5f; + effectPrefab = OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/ClayGooOrbEffect"); + orbDamageType = DamageType.ClayGoo; + } + base.duration = base.distanceToTarget / speed; + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + } + + public override void OnArrival() + { + if (!target) + { + return; + } + HealthComponent healthComponent = target.healthComponent; + if (!healthComponent) + { + return; + } + if (damageOrbType == DamageOrbType.ClayGooOrb) + { + CharacterBody component = healthComponent.GetComponent(); + if ((bool)component && (component.bodyFlags & CharacterBody.BodyFlags.ImmuneToGoo) != 0) + { + healthComponent.Heal(damageValue, default(ProcChainMask)); + return; + } + } + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = null; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + damageInfo.damageType = orbDamageType; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/DelayedHitOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/DelayedHitOrb.cs new file mode 100644 index 0000000..237485a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/DelayedHitOrb.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class DelayedHitOrb : GenericDamageOrb +{ + public float delay; + + public GameObject delayedEffectPrefab; + + public GameObject orbEffect; + + public override void Begin() + { + base.Begin(); + base.duration = delay; + } + + protected override GameObject GetOrbEffect() + { + return orbEffect; + } + + public override void OnArrival() + { + if ((bool)target && (bool)target.transform) + { + EffectManager.SpawnEffect(delayedEffectPrefab, new EffectData + { + origin = target.transform.position + }, transmit: true); + base.OnArrival(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/DevilOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/DevilOrb.cs new file mode 100644 index 0000000..3faed9f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/DevilOrb.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace RoR2.Orbs; + +public class DevilOrb : Orb +{ + public enum EffectType + { + Skull, + Wisp + } + + private const float speed = 30f; + + public float damageValue; + + public GameObject attacker; + + public TeamIndex teamIndex; + + public bool isCrit; + + public float scale; + + public ProcChainMask procChainMask; + + public float procCoefficient = 0.2f; + + public DamageColorIndex damageColorIndex; + + public EffectType effectType; + + public override void Begin() + { + base.duration = base.distanceToTarget / 30f; + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + GameObject effectPrefab = null; + switch (effectType) + { + case EffectType.Skull: + effectPrefab = OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/DevilOrbEffect"); + break; + case EffectType.Wisp: + effectPrefab = OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/WispOrbEffect"); + break; + } + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + } + + public override void OnArrival() + { + if ((bool)target) + { + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = null; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + } + } + } + + public HurtBox PickNextTarget(Vector3 position, float range) + { + BullseyeSearch bullseyeSearch = new BullseyeSearch(); + bullseyeSearch.searchOrigin = position; + bullseyeSearch.searchDirection = Vector3.zero; + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(teamIndex); + bullseyeSearch.filterByLoS = false; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; + bullseyeSearch.maxDistanceFilter = range; + bullseyeSearch.RefreshCandidates(); + List list = bullseyeSearch.GetResults().ToList(); + if (list.Count <= 0) + { + return null; + } + return list[Random.Range(0, list.Count)]; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/GenericDamageOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/GenericDamageOrb.cs new file mode 100644 index 0000000..a4d68c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/GenericDamageOrb.cs @@ -0,0 +1,72 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class GenericDamageOrb : Orb +{ + public float speed = 60f; + + public float damageValue; + + public GameObject attacker; + + public TeamIndex teamIndex; + + public bool isCrit; + + public float scale; + + public ProcChainMask procChainMask; + + public float procCoefficient = 0.2f; + + public DamageColorIndex damageColorIndex; + + public DamageTypeCombo damageType; + + public override void Begin() + { + base.duration = base.distanceToTarget / speed; + if ((bool)GetOrbEffect()) + { + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(GetOrbEffect(), effectData, transmit: true); + } + } + + protected virtual GameObject GetOrbEffect() + { + return null; + } + + public override void OnArrival() + { + if ((bool)target) + { + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = null; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + damageInfo.damageType = damageType; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/GoldOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/GoldOrb.cs new file mode 100644 index 0000000..e20deee --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/GoldOrb.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class GoldOrb : Orb +{ + public uint goldAmount; + + public bool scaleOrb = true; + + public float overrideDuration = 0.6f; + + public override void Begin() + { + if ((bool)target) + { + base.duration = overrideDuration; + float scale = (scaleOrb ? Mathf.Min((float)goldAmount / Run.instance.difficultyCoefficient, 1f) : 1f); + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/GoldOrbEffect"), effectData, transmit: true); + } + } + + public override void OnArrival() + { + if ((bool)target && (bool)target.healthComponent && (bool)target.healthComponent.body && (bool)target.healthComponent.body.master) + { + target.healthComponent.body.master.GiveMoney(goldAmount); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/HauntOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/HauntOrb.cs new file mode 100644 index 0000000..0b46999 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/HauntOrb.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class HauntOrb : Orb +{ + public float timeToArrive; + + public float scale; + + public override void Begin() + { + base.duration = timeToArrive + Random.Range(0f, 0.4f); + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/HauntOrbEffect"), effectData, transmit: true); + } + + public override void OnArrival() + { + if ((bool)target) + { + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent && (bool)healthComponent.body) + { + healthComponent.body.AddTimedBuff(RoR2Content.Buffs.AffixHaunted, 15f); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/HealOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/HealOrb.cs new file mode 100644 index 0000000..a4b593a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/HealOrb.cs @@ -0,0 +1,41 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class HealOrb : Orb +{ + public float healValue; + + public bool scaleOrb = true; + + public float overrideDuration = 0.3f; + + public override void Begin() + { + if ((bool)target) + { + base.duration = overrideDuration; + float scale = (scaleOrb ? Mathf.Min(healValue / target.healthComponent.fullHealth, 1f) : 1f); + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/HealthOrbEffect"), effectData, transmit: true); + } + } + + public override void OnArrival() + { + if ((bool)target) + { + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + healthComponent.Heal(healValue, default(ProcChainMask)); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/HuntressArrowOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/HuntressArrowOrb.cs new file mode 100644 index 0000000..4e7bd0a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/HuntressArrowOrb.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class HuntressArrowOrb : GenericDamageOrb +{ + public override void Begin() + { + speed = 120f; + base.Begin(); + } + + protected override GameObject GetOrbEffect() + { + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/ArrowOrbEffect"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/HuntressFlurryArrowOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/HuntressFlurryArrowOrb.cs new file mode 100644 index 0000000..1e5a852 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/HuntressFlurryArrowOrb.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class HuntressFlurryArrowOrb : HuntressArrowOrb +{ + public override void Begin() + { + base.Begin(); + speed = 80f; + } + + protected override GameObject GetOrbEffect() + { + if (isCrit) + { + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/FlurryArrowCritOrbEffect"); + } + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/FlurryArrowOrbEffect"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/IOrbFixedUpdateBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/IOrbFixedUpdateBehavior.cs new file mode 100644 index 0000000..f3db2d5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/IOrbFixedUpdateBehavior.cs @@ -0,0 +1,6 @@ +namespace RoR2.Orbs; + +public interface IOrbFixedUpdateBehavior +{ + void FixedUpdate(); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/InfusionOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/InfusionOrb.cs new file mode 100644 index 0000000..18db402 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/InfusionOrb.cs @@ -0,0 +1,35 @@ +namespace RoR2.Orbs; + +public class InfusionOrb : Orb +{ + private const float speed = 30f; + + public int maxHpValue; + + private Inventory targetInventory; + + public override void Begin() + { + base.duration = base.distanceToTarget / 30f; + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/InfusionOrbEffect"), effectData, transmit: true); + CharacterBody characterBody = target.GetComponent()?.healthComponent.GetComponent(); + if ((bool)characterBody) + { + targetInventory = characterBody.inventory; + } + } + + public override void OnArrival() + { + if ((bool)targetInventory) + { + targetInventory.AddInfusionBonus((uint)maxHpValue); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/ItemTakenOrbEffect.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/ItemTakenOrbEffect.cs new file mode 100644 index 0000000..99480e5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/ItemTakenOrbEffect.cs @@ -0,0 +1,52 @@ +using System.Collections; +using UnityEngine; + +namespace RoR2.Orbs; + +[RequireComponent(typeof(EffectComponent))] +public class ItemTakenOrbEffect : MonoBehaviour +{ + public TrailRenderer trailToColor; + + public ParticleSystem[] particlesToColor; + + public SpriteRenderer[] spritesToColor; + + public SpriteRenderer iconSpriteRenderer; + + private void OnEnable() + { + StartCoroutine(DelayedUpdateSprite()); + } + + private IEnumerator DelayedUpdateSprite() + { + yield return 0; + ItemDef itemDef = ItemCatalog.GetItemDef((ItemIndex)Util.UintToIntMinusOne(GetComponent().effectData.genericUInt)); + ColorCatalog.ColorIndex colorIndex = ColorCatalog.ColorIndex.Error; + Sprite sprite = null; + if (itemDef != null) + { + colorIndex = itemDef.colorIndex; + sprite = itemDef.pickupIconSprite; + } + Color color = ColorCatalog.GetColor(colorIndex); + if (trailToColor != null) + { + trailToColor.startColor *= color; + trailToColor.endColor *= color; + } + for (int i = 0; i < particlesToColor.Length; i++) + { + ParticleSystem obj = particlesToColor[i]; + ParticleSystem.MainModule main = obj.main; + main.startColor = color; + obj.Play(); + } + for (int j = 0; j < spritesToColor.Length; j++) + { + spritesToColor[j].color = color; + } + iconSpriteRenderer.sprite = sprite; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/ItemTransferOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/ItemTransferOrb.cs new file mode 100644 index 0000000..94089fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/ItemTransferOrb.cs @@ -0,0 +1,111 @@ +using System; +using HG; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.ResourceManagement.AsyncOperations; + +namespace RoR2.Orbs; + +public class ItemTransferOrb : Orb +{ + public ItemIndex itemIndex; + + public int stack; + + public Inventory inventoryToGrantTo; + + public Action onArrival = DefaultOnArrivalBehavior; + + public NetworkIdentity orbEffectTargetObjectOverride; + + public float travelDuration = 1f; + + private static GameObject orbEffectPrefab; + + [InitDuringStartup] + private static void Init() + { + AsyncOperationHandle asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Effects/OrbEffects/ItemTransferOrbEffect"); + asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) + { + orbEffectPrefab = x.Result; + }; + } + + public override void Begin() + { + base.duration = travelDuration; + if ((bool)target || (bool)orbEffectTargetObjectOverride) + { + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = base.duration, + genericUInt = Util.IntToUintPlusOne((int)itemIndex) + }; + if ((bool)orbEffectTargetObjectOverride) + { + effectData.SetNetworkedObjectReference(orbEffectTargetObjectOverride.gameObject); + } + else + { + effectData.SetHurtBoxReference(target); + } + EffectManager.SpawnEffect(orbEffectPrefab, effectData, transmit: true); + } + } + + public override void OnArrival() + { + onArrival?.Invoke(this); + } + + public static void DefaultOnArrivalBehavior(ItemTransferOrb orb) + { + if ((bool)orb.inventoryToGrantTo) + { + orb.inventoryToGrantTo.GiveItem(orb.itemIndex, orb.stack); + } + } + + public static ItemTransferOrb DispatchItemTransferOrb(Vector3 origin, Inventory inventoryToGrantTo, ItemIndex itemIndex, int itemStack, Action onArrivalBehavior = null, Either orbDestinationOverride = default(Either)) + { + if (onArrivalBehavior == null) + { + onArrivalBehavior = DefaultOnArrivalBehavior; + } + ItemTransferOrb itemTransferOrb = new ItemTransferOrb(); + itemTransferOrb.origin = origin; + itemTransferOrb.inventoryToGrantTo = inventoryToGrantTo; + itemTransferOrb.itemIndex = itemIndex; + itemTransferOrb.stack = itemStack; + itemTransferOrb.onArrival = onArrivalBehavior; + NetworkIdentity a = orbDestinationOverride.a; + HurtBox b = orbDestinationOverride.b; + if (!b) + { + if ((bool)inventoryToGrantTo) + { + CharacterMaster component = inventoryToGrantTo.GetComponent(); + if ((bool)component) + { + CharacterBody body = component.GetBody(); + if ((bool)body) + { + itemTransferOrb.target = body.mainHurtBox; + } + } + } + if ((bool)a) + { + itemTransferOrb.orbEffectTargetObjectOverride = a; + } + } + else + { + itemTransferOrb.target = b; + } + OrbManager.instance.AddOrb(itemTransferOrb); + return itemTransferOrb; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/LightningOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/LightningOrb.cs new file mode 100644 index 0000000..637c247 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/LightningOrb.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace RoR2.Orbs; + +public class LightningOrb : Orb +{ + public enum LightningType + { + Ukulele, + Tesla, + BFG, + TreePoisonDart, + HuntressGlaive, + Loader, + RazorWire, + CrocoDisease, + MageLightning, + AntlerShield, + BeadDamage, + Count + } + + public float speed = 100f; + + public float damageValue; + + public GameObject attacker; + + public GameObject inflictor; + + public int bouncesRemaining; + + public List bouncedObjects; + + public TeamIndex teamIndex; + + public bool isCrit; + + public ProcChainMask procChainMask; + + public float procCoefficient = 1f; + + public DamageColorIndex damageColorIndex; + + public float range = 20f; + + public float damageCoefficientPerBounce = 1f; + + public int targetsToFindPerBounce = 1; + + public DamageTypeCombo damageType = DamageType.Generic; + + private bool canBounceOnSameTarget; + + private bool failedToKill; + + public LightningType lightningType; + + private BullseyeSearch search; + + public static event Action onLightningOrbKilledOnAllBounces; + + public override void Begin() + { + base.duration = 0.1f; + string path = null; + switch (lightningType) + { + case LightningType.Ukulele: + path = "Prefabs/Effects/OrbEffects/LightningOrbEffect"; + break; + case LightningType.Tesla: + path = "Prefabs/Effects/OrbEffects/TeslaOrbEffect"; + break; + case LightningType.BFG: + path = "Prefabs/Effects/OrbEffects/BeamSphereOrbEffect"; + base.duration = 0.4f; + break; + case LightningType.HuntressGlaive: + path = "Prefabs/Effects/OrbEffects/HuntressGlaiveOrbEffect"; + base.duration = base.distanceToTarget / speed; + canBounceOnSameTarget = true; + break; + case LightningType.TreePoisonDart: + path = "Prefabs/Effects/OrbEffects/TreePoisonDartOrbEffect"; + speed = 40f; + base.duration = base.distanceToTarget / speed; + break; + case LightningType.Loader: + path = "Prefabs/Effects/OrbEffects/LoaderLightningOrbEffect"; + break; + case LightningType.RazorWire: + path = "Prefabs/Effects/OrbEffects/RazorwireOrbEffect"; + base.duration = 0.2f; + break; + case LightningType.CrocoDisease: + path = "Prefabs/Effects/OrbEffects/CrocoDiseaseOrbEffect"; + base.duration = 0.6f; + targetsToFindPerBounce = 2; + break; + case LightningType.MageLightning: + path = "Prefabs/Effects/OrbEffects/MageLightningOrbEffect"; + base.duration = 0.1f; + break; + case LightningType.AntlerShield: + path = "Prefabs/Effects/OrbEffects/NegateAttackOrbEffect"; + base.duration = 0.2f; + break; + case LightningType.BeadDamage: + path = "Prefabs/Effects/OrbEffects/BeadDamageOrbEffect"; + base.duration = 0.2f; + break; + } + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get(path), effectData, transmit: true); + } + + public override void OnArrival() + { + if (!target) + { + return; + } + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = inflictor; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + damageInfo.damageType = damageType; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + } + failedToKill |= !healthComponent || healthComponent.alive; + if (bouncesRemaining > 0) + { + for (int i = 0; i < targetsToFindPerBounce; i++) + { + if (bouncedObjects != null) + { + if (canBounceOnSameTarget) + { + bouncedObjects.Clear(); + } + bouncedObjects.Add(target.healthComponent); + } + HurtBox hurtBox = PickNextTarget(target.transform.position); + if ((bool)hurtBox) + { + LightningOrb lightningOrb = new LightningOrb(); + lightningOrb.search = search; + lightningOrb.origin = target.transform.position; + lightningOrb.target = hurtBox; + lightningOrb.attacker = attacker; + lightningOrb.inflictor = inflictor; + lightningOrb.teamIndex = teamIndex; + lightningOrb.damageValue = damageValue * damageCoefficientPerBounce; + lightningOrb.bouncesRemaining = bouncesRemaining - 1; + lightningOrb.isCrit = isCrit; + lightningOrb.bouncedObjects = bouncedObjects; + lightningOrb.lightningType = lightningType; + lightningOrb.procChainMask = procChainMask; + lightningOrb.procCoefficient = procCoefficient; + lightningOrb.damageColorIndex = damageColorIndex; + lightningOrb.damageCoefficientPerBounce = damageCoefficientPerBounce; + lightningOrb.speed = speed; + lightningOrb.range = range; + lightningOrb.damageType = damageType; + lightningOrb.failedToKill = failedToKill; + OrbManager.instance.AddOrb(lightningOrb); + } + } + } + else if (!failedToKill) + { + LightningOrb.onLightningOrbKilledOnAllBounces?.Invoke(this); + } + } + + public HurtBox PickNextTarget(Vector3 position) + { + if (search == null) + { + search = new BullseyeSearch(); + } + search.searchOrigin = position; + search.searchDirection = Vector3.zero; + search.teamMaskFilter = TeamMask.allButNeutral; + search.teamMaskFilter.RemoveTeam(teamIndex); + search.filterByLoS = false; + search.sortMode = BullseyeSearch.SortMode.Distance; + search.maxDistanceFilter = range; + search.RefreshCandidates(); + HurtBox hurtBox = (from v in search.GetResults() + where !bouncedObjects.Contains(v.healthComponent) + select v).FirstOrDefault(); + if ((bool)hurtBox) + { + bouncedObjects.Add(hurtBox.healthComponent); + } + return hurtBox; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/LightningStrikeOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/LightningStrikeOrb.cs new file mode 100644 index 0000000..52563d0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/LightningStrikeOrb.cs @@ -0,0 +1,60 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class LightningStrikeOrb : GenericDamageOrb, IOrbFixedUpdateBehavior +{ + private Vector3 lastKnownTargetPosition; + + private static readonly float positionLockDuration = 0.3f; + + public override void Begin() + { + base.Begin(); + base.duration = 0.5f; + if ((bool)target) + { + lastKnownTargetPosition = target.transform.position; + } + } + + protected override GameObject GetOrbEffect() + { + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/LightningStrikeOrbEffect"); + } + + public override void OnArrival() + { + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/ImpactEffects/LightningStrikeImpact"), new EffectData + { + origin = lastKnownTargetPosition + }, transmit: true); + if ((bool)attacker) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = attacker; + blastAttack.baseDamage = damageValue; + blastAttack.baseForce = 0f; + blastAttack.bonusForce = Vector3.down * 3000f; + blastAttack.crit = isCrit; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.damageType = DamageType.Stun1s; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.inflictor = null; + blastAttack.position = lastKnownTargetPosition; + blastAttack.procChainMask = procChainMask; + blastAttack.procCoefficient = procCoefficient; + blastAttack.radius = 3f; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(attacker); + blastAttack.Fire(); + } + } + + public void FixedUpdate() + { + if ((bool)target && base.timeUntilArrival >= positionLockDuration) + { + lastKnownTargetPosition = target.transform.position; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/LunarDetonatorOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/LunarDetonatorOrb.cs new file mode 100644 index 0000000..bf71337 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/LunarDetonatorOrb.cs @@ -0,0 +1,85 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class LunarDetonatorOrb : Orb +{ + public float travelSpeed = 60f; + + public float baseDamage; + + public float damagePerStack; + + public GameObject attacker; + + public bool isCrit; + + public ProcChainMask procChainMask; + + public float procCoefficient; + + public DamageColorIndex damageColorIndex; + + public GameObject detonationEffectPrefab; + + public GameObject orbEffectPrefab; + + public override void Begin() + { + base.duration = base.distanceToTarget / travelSpeed; + EffectData effectData = new EffectData + { + scale = 1f, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + if ((bool)orbEffectPrefab) + { + EffectManager.SpawnEffect(orbEffectPrefab, effectData, transmit: true); + } + } + + public override void OnArrival() + { + base.OnArrival(); + if (!target) + { + return; + } + HealthComponent healthComponent = target.healthComponent; + if (!healthComponent) + { + return; + } + CharacterBody body = healthComponent.body; + if ((bool)body) + { + int buffCount = body.GetBuffCount(RoR2Content.Buffs.LunarDetonationCharge); + if (buffCount > 0) + { + body.ClearTimedBuffs(RoR2Content.Buffs.LunarDetonationCharge); + Vector3 position = target.transform.position; + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = baseDamage + damagePerStack * (float)buffCount; + damageInfo.attacker = attacker; + damageInfo.inflictor = null; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = position; + damageInfo.damageColorIndex = damageColorIndex; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + EffectManager.SpawnEffect(detonationEffectPrefab, new EffectData + { + origin = position, + rotation = Quaternion.identity, + scale = Mathf.Log(buffCount, 5f) + }, transmit: true); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/MicroMissileOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/MicroMissileOrb.cs new file mode 100644 index 0000000..c16e82a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/MicroMissileOrb.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class MicroMissileOrb : GenericDamageOrb +{ + public override void Begin() + { + speed = 55f; + base.Begin(); + } + + protected override GameObject GetOrbEffect() + { + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/MicroMissileOrbEffect"); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/MissileVoidOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/MissileVoidOrb.cs new file mode 100644 index 0000000..35af735 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/MissileVoidOrb.cs @@ -0,0 +1,18 @@ +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace RoR2.Orbs; + +public class MissileVoidOrb : GenericDamageOrb +{ + public override void Begin() + { + speed = 75f; + base.Begin(); + } + + protected override GameObject GetOrbEffect() + { + return Addressables.LoadAssetAsync("RoR2/DLC1/MissileVoid/MissileVoidOrbEffect.prefab").WaitForCompletion(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/Orb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/Orb.cs new file mode 100644 index 0000000..80f0a47 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/Orb.cs @@ -0,0 +1,74 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class Orb +{ + public Vector3 origin; + + public HurtBox target; + + public Orb nextOrb; + + public float arrivalTime; + + public int instanceID = -1; + + protected static int _InstanceCount; + + protected OrbPool _OwningPool; + + public float duration { get; protected set; } + + public float timeUntilArrival => arrivalTime - OrbManager.instance.time; + + public static int InstanceCount => _InstanceCount; + + protected float distanceToTarget + { + get + { + if ((bool)target) + { + return Vector3.Distance(target.transform.position, origin); + } + return 0f; + } + } + + public void SetOwningPool(OrbPool inOwningPool) + { + _OwningPool = inOwningPool; + } + + public Orb() + { + _InstanceCount++; + } + + public virtual void Reset() + { + origin = Vector3.zero; + target = null; + duration = 0f; + arrivalTime = 0f; + nextOrb = null; + } + + public virtual void Begin() + { + } + + public virtual void OnArrival() + { + ReturnToPool(); + } + + public virtual void ReturnToPool() + { + if (OrbPool.UsePools && _OwningPool != null) + { + _OwningPool.ReturnObject(this); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbCatalog.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbCatalog.cs new file mode 100644 index 0000000..c4ffafd --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbCatalog.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace RoR2.Orbs; + +public static class OrbCatalog +{ + private static readonly Dictionary typeToIndex; + + private static Type[] indexToType; + + private static void GenerateCatalog() + { + indexToType = (from t in typeof(Orb).Assembly.GetTypes() + where t.IsSubclassOf(typeof(Orb)) + orderby t.Name + select t).ToArray(); + typeToIndex.Clear(); + Type[] array = indexToType; + foreach (Type key in array) + { + typeToIndex[key] = typeToIndex.Count; + } + } + + static OrbCatalog() + { + typeToIndex = new Dictionary(); + indexToType = Array.Empty(); + GenerateCatalog(); + } + + public static int FindIndex(Type type) + { + if (typeToIndex.TryGetValue(type, out var value)) + { + return value; + } + return -1; + } + + public static Type FindType(int index) + { + if (index < 0 || index >= indexToType.Length) + { + return null; + } + return indexToType[index]; + } + + public static Orb Instantiate(int index) + { + return Instantiate(FindType(index)); + } + + public static Orb Instantiate(Type type) + { + if (type == null) + { + return null; + } + return (Orb)Activator.CreateInstance(type); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbEffect.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbEffect.cs new file mode 100644 index 0000000..abb3a33 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbEffect.cs @@ -0,0 +1,381 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.Orbs; + +[RequireComponent(typeof(EffectComponent))] +public class OrbEffect : MonoBehaviour +{ + private Transform targetTransform; + + private float duration; + + private Vector3 startPosition; + + private Vector3 previousPosition; + + private Vector3 lastKnownTargetPosition; + + private float age; + + [HideInInspector] + public Transform parentObjectTransform; + + [Header("Curve Parameters")] + public Vector3 startVelocity1; + + public Vector3 startVelocity2; + + public Vector3 endVelocity1; + + public Vector3 endVelocity2; + + private Vector3 startVelocity; + + private Vector3 endVelocity; + + public AnimationCurve movementCurve; + + public BezierCurveLine bezierCurveLine; + + public bool faceMovement = true; + + public bool callArrivalIfTargetIsGone; + + [Header("Start Effect")] + [Tooltip("An effect prefab to spawn on Start")] + public GameObject startEffect; + + public float startEffectScale = 1f; + + public bool startEffectCopiesRotation; + + [Header("End Effect")] + [Tooltip("An effect prefab to spawn on end")] + public GameObject endEffect; + + public float endEffectScale = 1f; + + public bool endEffectCopiesRotation; + + [Header("Arrival Behavior")] + public UnityEvent onArrival; + + protected EffectComponent _effectComponent; + + protected EffectManagerHelper _effectManagerHelper; + + protected EffectManagerHelper _parentEffectManagerHelper; + + protected EffectData _effectData; + + protected List _trailRenderers; + + protected bool _arrived; + + protected bool _startCalled; + + private bool orbEffectHasOnArrivalAnimateShaderAlpha; + + public int singletonArrayIndex = -1; + + public void PrepForPoolUsage() + { + if (onArrival == null) + { + return; + } + int num = -1; + int persistentEventCount = onArrival.GetPersistentEventCount(); + for (int i = 0; i < persistentEventCount; i++) + { + UnityEngine.Object persistentTarget = onArrival.GetPersistentTarget(i); + string persistentMethodName = onArrival.GetPersistentMethodName(i); + if (persistentMethodName == "DetachChildren") + { + num = i; + } + else if (persistentMethodName == "set_enabled" && persistentTarget.GetType() == typeof(AnimateShaderAlpha)) + { + orbEffectHasOnArrivalAnimateShaderAlpha = true; + AnimateShaderAlpha animateShaderAlpha = persistentTarget as AnimateShaderAlpha; + if (!animateShaderAlpha.continueExistingAfterTimeMaxIsReached) + { + animateShaderAlpha.OnFinished.AddListener(OnAllEffectsOnArrivalCompleted); + } + if (animateShaderAlpha.destroyOnEnd) + { + animateShaderAlpha.destroyOnEnd = false; + animateShaderAlpha.disableOnEnd = true; + } + } + } + if (num != -1) + { + onArrival.SetPersistentListenerState(num, UnityEventCallState.Off); + } + if (_trailRenderers != null) + { + return; + } + TrailRenderer[] components = base.gameObject.GetComponents(); + if (components != null && components.Length != 0) + { + if (_trailRenderers == null) + { + _trailRenderers = new List(); + } + _trailRenderers.AddRange(components); + } + TrailRenderer[] componentsInChildren = base.gameObject.GetComponentsInChildren(includeInactive: true); + if (componentsInChildren != null && componentsInChildren.Length != 0) + { + if (_trailRenderers == null) + { + _trailRenderers = new List(); + } + _trailRenderers.AddRange(componentsInChildren); + } + } + + private void OnAllEffectsOnArrivalCompleted() + { + if (_effectManagerHelper != null && _effectManagerHelper.OwningPool != null) + { + _effectManagerHelper.OwningPool.ReturnObject(_effectManagerHelper); + return; + } + if (_effectManagerHelper != null) + { + Debug.LogErrorFormat("OrbEffect: No owning pool set. {0} ({1})", base.gameObject.name, base.gameObject.GetInstanceID()); + } + UnityEngine.Object.Destroy(base.gameObject); + } + + public void Reset() + { + if (!_startCalled) + { + return; + } + if (_effectManagerHelper == null) + { + _effectManagerHelper = base.gameObject.GetComponent(); + } + if (_effectComponent == null) + { + _effectComponent = base.gameObject.GetComponent(); + } + if (_parentEffectManagerHelper == null) + { + _parentEffectManagerHelper = ((base.gameObject.transform.parent != null) ? base.gameObject.transform.parent.gameObject.GetComponent() : null); + } + if (_effectData != null) + { + _effectData.Reset(); + } + targetTransform = null; + duration = 0f; + startPosition = Vector3.zero; + previousPosition = Vector3.zero; + lastKnownTargetPosition = Vector3.zero; + age = 0f; + startVelocity = Vector3.zero; + endVelocity = Vector3.zero; + parentObjectTransform = null; + startPosition = _effectComponent.effectData.origin; + previousPosition = startPosition; + GameObject gameObject = _effectComponent.effectData.ResolveHurtBoxReference(); + targetTransform = (gameObject ? gameObject.transform : null); + duration = _effectComponent.effectData.genericFloat; + if (duration == 0f) + { + Debug.LogFormat("Zero duration for effect \"{0}\" {1}:{2}:{3}.{4}", base.gameObject.name, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond); + if (!EffectManager.UsePools) + { + UnityEngine.Object.Destroy(base.gameObject); + return; + } + if (_effectManagerHelper != null && _effectManagerHelper.OwningPool != null) + { + _effectManagerHelper.OwningPool.ReturnObject(_effectManagerHelper); + return; + } + if (_effectManagerHelper != null) + { + Debug.LogErrorFormat("OrbEffect: No owning pool set. {0} ({1})", base.gameObject.name, base.gameObject.GetInstanceID()); + } + UnityEngine.Object.Destroy(base.gameObject); + return; + } + lastKnownTargetPosition = (targetTransform ? targetTransform.position : startPosition); + if ((bool)startEffect) + { + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.Reset(); + _effectData.origin = base.transform.position; + _effectData.scale = startEffectScale; + if (startEffectCopiesRotation) + { + _effectData.rotation = base.transform.rotation; + } + EffectManager.SpawnEffect(startEffect, _effectData, transmit: false); + } + startVelocity.x = Mathf.Lerp(startVelocity1.x, startVelocity2.x, UnityEngine.Random.value); + startVelocity.y = Mathf.Lerp(startVelocity1.y, startVelocity2.y, UnityEngine.Random.value); + startVelocity.z = Mathf.Lerp(startVelocity1.z, startVelocity2.z, UnityEngine.Random.value); + endVelocity.x = Mathf.Lerp(endVelocity1.x, endVelocity2.x, UnityEngine.Random.value); + endVelocity.y = Mathf.Lerp(endVelocity1.y, endVelocity2.y, UnityEngine.Random.value); + endVelocity.z = Mathf.Lerp(endVelocity1.z, endVelocity2.z, UnityEngine.Random.value); + if (_trailRenderers != null) + { + foreach (TrailRenderer trailRenderer in _trailRenderers) + { + trailRenderer.Clear(); + } + } + _arrived = false; + UpdateOrb(0f); + } + + private void OnEnable() + { + OrbEffectSingleton.RegisterInstance(this); + } + + private void OnDisable() + { + OrbEffectSingleton.UnregisterInstance(this); + } + + private void Start() + { + _startCalled = true; + EffectComponent component = GetComponent(); + _effectComponent = component; + _effectManagerHelper = base.gameObject.GetComponent(); + _parentEffectManagerHelper = ((base.gameObject.transform.parent != null) ? base.gameObject.transform.parent.gameObject.GetComponent() : null); + Reset(); + } + + public void UpdateOrb(float deltaTime) + { + if (_arrived) + { + return; + } + if ((bool)parentObjectTransform) + { + startPosition = parentObjectTransform.position; + } + if ((bool)targetTransform) + { + lastKnownTargetPosition = targetTransform.position; + } + float num = ((duration == 0f) ? 0f : Mathf.Clamp01(age / duration)); + float num2 = movementCurve.Evaluate(num); + Vector3 vector = Vector3.Lerp(startPosition + startVelocity * num2, lastKnownTargetPosition + endVelocity * (1f - num2), num2); + base.transform.position = vector; + if (faceMovement && vector != previousPosition) + { + base.transform.forward = vector - previousPosition; + } + UpdateBezier(); + if ((num >= 1f || (callArrivalIfTargetIsGone && targetTransform == null)) && !_arrived) + { + onArrival.Invoke(); + if ((bool)endEffect) + { + if (_effectData == null) + { + _effectData = new EffectData(); + } + _effectData.Reset(); + _effectData.origin = base.transform.position; + _effectData.scale = endEffectScale; + if (endEffectCopiesRotation) + { + _effectData.rotation = base.transform.rotation; + } + EffectManager.SpawnEffect(endEffect, _effectData, transmit: false); + } + if (!EffectManager.UsePools) + { + UnityEngine.Object.Destroy(base.gameObject); + } + else if (_effectManagerHelper != null && _effectManagerHelper.OwningPool != null) + { + if (!_effectManagerHelper.HasDestroyOnTimer && !_effectManagerHelper.HasAnimateShaderAlphas && !orbEffectHasOnArrivalAnimateShaderAlpha) + { + _effectManagerHelper.OwningPool.ReturnObject(_effectManagerHelper); + } + } + else + { + if (_effectManagerHelper != null) + { + Debug.LogErrorFormat("OrbEffect: No owning pool set. {0} ({1})", base.gameObject.name, base.gameObject.GetInstanceID()); + } + UnityEngine.Object.Destroy(base.gameObject); + } + _arrived = true; + } + if (!_arrived) + { + previousPosition = vector; + age += deltaTime; + } + } + + private void UpdateBezier() + { + if ((bool)bezierCurveLine) + { + bezierCurveLine.p1 = startPosition; + bezierCurveLine.v0 = endVelocity; + bezierCurveLine.v1 = startVelocity; + bezierCurveLine.UpdateBezier(0f); + } + } + + public void InstantiatePrefab(GameObject prefab) + { + UnityEngine.Object.Instantiate(prefab, base.transform.position, base.transform.rotation); + } + + public void InstantiateEffect(GameObject prefab) + { + EffectManager.SpawnEffect(prefab, new EffectData + { + origin = base.transform.position + }, transmit: false); + } + + public void InstantiateEffectCopyRotation(GameObject prefab) + { + EffectManager.SpawnEffect(prefab, new EffectData + { + origin = base.transform.position, + rotation = base.transform.rotation + }, transmit: false); + } + + public void InstantiateEffectOppositeFacing(GameObject prefab) + { + EffectManager.SpawnEffect(prefab, new EffectData + { + origin = base.transform.position, + rotation = Util.QuaternionSafeLookRotation(-base.transform.forward) + }, transmit: false); + } + + public void InstantiatePrefabOppositeFacing(GameObject prefab) + { + UnityEngine.Object.Instantiate(prefab, base.transform.position, Util.QuaternionSafeLookRotation(-base.transform.forward)); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbManager.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbManager.cs new file mode 100644 index 0000000..5fef963 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbManager.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RoR2.Orbs; + +public class OrbManager : MonoBehaviour +{ + private List travelingOrbs = new List(); + + private float nextOrbArrival = float.PositiveInfinity; + + private List orbsWithFixedUpdateBehavior = new List(); + + public static OrbManager instance { get; private set; } + + public float time { get; private set; } + + private void OnEnable() + { + if (!instance) + { + instance = this; + return; + } + Debug.LogErrorFormat(this, "Duplicate instance of singleton class {0}. Only one should exist at a time.", GetType().Name); + } + + private void OnDisable() + { + if (instance == this) + { + instance = null; + } + } + + private void FixedUpdate() + { + time += Time.fixedDeltaTime; + for (int i = 0; i < orbsWithFixedUpdateBehavior.Count; i++) + { + orbsWithFixedUpdateBehavior[i].FixedUpdate(); + } + if (!(nextOrbArrival <= time)) + { + return; + } + nextOrbArrival = float.PositiveInfinity; + for (int num = travelingOrbs.Count - 1; num >= 0; num--) + { + Orb orb = travelingOrbs[num]; + if (orb.arrivalTime <= time) + { + travelingOrbs.RemoveAt(num); + if (orb is IOrbFixedUpdateBehavior item) + { + orbsWithFixedUpdateBehavior.Remove(item); + } + orb.OnArrival(); + } + else if (nextOrbArrival > orb.arrivalTime) + { + nextOrbArrival = orb.arrivalTime; + } + } + } + + public void ForceImmediateArrival(Orb orb) + { + orb.OnArrival(); + travelingOrbs.Remove(orb); + } + + public void AddOrb(Orb orb) + { + orb.Begin(); + orb.arrivalTime = time + orb.duration; + travelingOrbs.Add(orb); + if (orb is IOrbFixedUpdateBehavior item) + { + orbsWithFixedUpdateBehavior.Add(item); + } + if (nextOrbArrival > orb.arrivalTime) + { + nextOrbArrival = orb.arrivalTime; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbPool.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbPool.cs new file mode 100644 index 0000000..da4618c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbPool.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Grumpy; +using UnityEngine; + +namespace RoR2.Orbs; + +public class OrbPool : GenericPool +{ + protected Type _OrbType; + + protected static bool _VerboseLogging = false; + + protected static Dictionary _OrbPoolMap = new Dictionary(); + + protected static bool _UsePools = true; + + public static bool VerboseLogging => _VerboseLogging; + + public static bool UsePools => _UsePools; + + public static void ToggleVerboseLogging() + { + _VerboseLogging = !_VerboseLogging; + Debug.LogFormat("Orb pooling {0}", _VerboseLogging ? "ENABLED" : "DISABLED"); + } + + public void Initialize(Type inOrbType, int inMaxSize, int inStartSize) + { + _OrbType = inOrbType; + base.PoolName = _OrbType.ToString(); + base.Initialize(inMaxSize, inStartSize); + } + + protected override Orb CreateNewObject(bool inPoolEntry = true) + { + if (_OrbType != null) + { + Orb orb = Activator.CreateInstance(_OrbType) as Orb; + orb.instanceID = _Pool.Count + _InUse.Count; + if (VerboseLogging) + { + Debug.LogFormat("OrbPool: {0} created instance {1} ({2})...", base.PoolName, _OrbType.ToString(), orb.instanceID); + } + return orb; + } + Debug.LogError("OrbPool: No type set!"); + return null; + } + + protected override void DestroyObject(Orb inObject) + { + } + + public void DumpPool(StringBuilder inDumpSB = null) + { + StringBuilder obj = inDumpSB ?? new StringBuilder(); + obj.AppendFormat("OrbPool {0}\n", base.PoolName); + obj.AppendFormat("\t Pool Count: {0}\n", _Pool.Count); + obj.AppendFormat("\tInUse Count: {0}\n", _InUse.Count); + } + + public static void TogglePooling() + { + _UsePools = !_UsePools; + Debug.LogFormat("Orb pooling is {0}", _UsePools ? "ENABLED" : "DISABLED"); + } + + protected static void CreatePoolIfNotPresent(Type inOrbType) + { + if (!_OrbPoolMap.ContainsKey(inOrbType)) + { + OrbPool orbPool = new OrbPool(); + orbPool.AlwaysGrowable = true; + orbPool.Initialize(inOrbType, 1, 1); + _OrbPoolMap.Add(inOrbType, orbPool); + } + } + + public static Orb GetPooledOrb(Type inOrbType) + { + CreatePoolIfNotPresent(inOrbType); + OrbPool orbPool = _OrbPoolMap[inOrbType]; + Orb @object = orbPool.GetObject(); + if (@object != null) + { + @object.SetOwningPool(orbPool); + @object.Reset(); + } + return @object; + } + + public static void ClearAllPools() + { + Debug.LogWarning("OrbPool: Clearing all pools"); + foreach (OrbPool value in _OrbPoolMap.Values) + { + value.Reset(); + } + _OrbPoolMap.Clear(); + } + + public static void DumpPools() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbStorageUtility.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbStorageUtility.cs new file mode 100644 index 0000000..d83a890 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/OrbStorageUtility.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RoR2.Orbs; + +public static class OrbStorageUtility +{ + private static Dictionary _orbDictionary = new Dictionary(); + + public static GameObject Get(string path) + { + if (!_orbDictionary.ContainsKey(path)) + { + _orbDictionary.Add(path, LegacyResourcesAPI.Load(path)); + } + return _orbDictionary[path]; + } + + public static void Clear() + { + _orbDictionary.Clear(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/SimpleLightningStrikeOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/SimpleLightningStrikeOrb.cs new file mode 100644 index 0000000..6634480 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/SimpleLightningStrikeOrb.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class SimpleLightningStrikeOrb : GenericDamageOrb, IOrbFixedUpdateBehavior +{ + private Vector3 lastKnownTargetPosition; + + public override void Begin() + { + base.Begin(); + base.duration = 0.25f; + if ((bool)target) + { + lastKnownTargetPosition = target.transform.position; + } + } + + protected override GameObject GetOrbEffect() + { + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/SimpleLightningStrikeOrbEffect"); + } + + public override void OnArrival() + { + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/ImpactEffects/SimpleLightningStrikeImpact"), new EffectData + { + origin = lastKnownTargetPosition + }, transmit: true); + if ((bool)attacker) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = attacker; + blastAttack.baseDamage = damageValue; + blastAttack.baseForce = 0f; + blastAttack.bonusForce = Vector3.down * 1500f; + blastAttack.crit = isCrit; + blastAttack.damageColorIndex = DamageColorIndex.Item; + blastAttack.falloffModel = BlastAttack.FalloffModel.None; + blastAttack.inflictor = null; + blastAttack.position = lastKnownTargetPosition; + blastAttack.procChainMask = procChainMask; + blastAttack.procCoefficient = procCoefficient; + blastAttack.radius = 3f; + blastAttack.teamIndex = TeamComponent.GetObjectTeam(attacker); + blastAttack.Fire(); + } + } + + public void FixedUpdate() + { + if ((bool)target) + { + lastKnownTargetPosition = target.transform.position; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/SquidOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/SquidOrb.cs new file mode 100644 index 0000000..177218c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/SquidOrb.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class SquidOrb : GenericDamageOrb +{ + public float forceScalar; + + public override void Begin() + { + speed = 120f; + base.Begin(); + } + + protected override GameObject GetOrbEffect() + { + return OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/SquidOrbEffect"); + } + + public override void OnArrival() + { + if (!target) + { + return; + } + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + Vector3 force = target.transform.position - origin; + if (force.sqrMagnitude > 0f) + { + force.Normalize(); + force *= forceScalar; + } + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = null; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + damageInfo.damageType = damageType; + damageInfo.force = force; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/TitanRechargeOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/TitanRechargeOrb.cs new file mode 100644 index 0000000..8c83808 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/TitanRechargeOrb.cs @@ -0,0 +1,24 @@ +namespace RoR2.Orbs; + +public class TitanRechargeOrb : Orb +{ + public int targetRockInt; + + public TitanRockController titanRockController; + + public override void Begin() + { + base.duration = 1f; + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/HealthOrbEffect"), effectData, transmit: true); + } + + public override void OnArrival() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/VendingMachineOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/VendingMachineOrb.cs new file mode 100644 index 0000000..5a52d3b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/VendingMachineOrb.cs @@ -0,0 +1,42 @@ +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace RoR2.Orbs; + +public class VendingMachineOrb : Orb +{ + public float healFraction; + + public bool scaleOrb = true; + + public float speed = 10f; + + public override void Begin() + { + if ((bool)target) + { + base.duration = Mathf.Max(1f, base.distanceToTarget / speed); + float scale = (scaleOrb ? Mathf.Min(healFraction, 1f) : 1f); + EffectData effectData = new EffectData + { + scale = scale, + origin = origin, + genericFloat = base.duration + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(Addressables.LoadAssetAsync("RoR2/DLC1/VendingMachine/VendingMachineOrbEffect.prefab").WaitForCompletion(), effectData, transmit: true); + } + } + + public override void OnArrival() + { + if ((bool)target) + { + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + healthComponent.HealFraction(healFraction, default(ProcChainMask)); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Orbs/VoidLightningOrb.cs b/ilspy_dump/ror2_csproj/RoR2.Orbs/VoidLightningOrb.cs new file mode 100644 index 0000000..1d9eb77 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Orbs/VoidLightningOrb.cs @@ -0,0 +1,95 @@ +using UnityEngine; + +namespace RoR2.Orbs; + +public class VoidLightningOrb : Orb, IOrbFixedUpdateBehavior +{ + public float damageValue; + + public GameObject attacker; + + public GameObject inflictor; + + public int totalStrikes; + + public float secondsPerStrike = 0.5f; + + public TeamIndex teamIndex; + + public bool isCrit; + + public ProcChainMask procChainMask; + + public float procCoefficient = 1f; + + public DamageColorIndex damageColorIndex; + + public DamageTypeCombo damageType = DamageType.Generic; + + private GameObject effectPrefab; + + private float accumulatedTime; + + public override void Begin() + { + accumulatedTime = 0f; + base.duration = (float)(totalStrikes - 1) * secondsPerStrike; + effectPrefab = OrbStorageUtility.Get("Prefabs/Effects/OrbEffects/VoidLightningOrbEffect"); + Strike(); + } + + public override void OnArrival() + { + } + + public void FixedUpdate() + { + accumulatedTime += Time.fixedDeltaTime; + while (accumulatedTime > secondsPerStrike) + { + accumulatedTime -= secondsPerStrike; + if ((bool)target) + { + origin = target.transform.position; + Strike(); + } + } + } + + private void Strike() + { + if (!target) + { + return; + } + HealthComponent healthComponent = target.healthComponent; + if ((bool)healthComponent) + { + DamageInfo damageInfo = new DamageInfo(); + damageInfo.damage = damageValue; + damageInfo.attacker = attacker; + damageInfo.inflictor = inflictor; + damageInfo.force = Vector3.zero; + damageInfo.crit = isCrit; + damageInfo.procChainMask = procChainMask; + damageInfo.procCoefficient = procCoefficient; + damageInfo.position = target.transform.position; + damageInfo.damageColorIndex = damageColorIndex; + damageInfo.damageType = damageType; + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject); + if ((bool)target.hurtBoxGroup) + { + target = target.hurtBoxGroup.hurtBoxes[Random.Range(0, target.hurtBoxGroup.hurtBoxes.Length)]; + } + EffectData effectData = new EffectData + { + origin = origin, + genericFloat = 0.1f + }; + effectData.SetHurtBoxReference(target); + EffectManager.SpawnEffect(effectPrefab, effectData, transmit: true); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcess/SobelCommandBuffer.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcess/SobelCommandBuffer.cs new file mode 100644 index 0000000..a42782f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcess/SobelCommandBuffer.cs @@ -0,0 +1,160 @@ +using System; +using UnityEngine; +using UnityEngine.AddressableAssets; +using UnityEngine.Experimental.Rendering; +using UnityEngine.Rendering; +using UnityEngine.ResourceManagement.AsyncOperations; + +namespace RoR2.PostProcess; + +[RequireComponent(typeof(Camera))] +[ExecuteAlways] +public class SobelCommandBuffer : MonoBehaviour +{ + public CameraEvent cameraEvent = CameraEvent.BeforeLighting; + + private Camera camera; + + private RenderTexture sobelInfoTex; + + private CommandBuffer sobelCommandBuffer; + + private CameraEvent sobelCommandBufferSubscribedEvent; + + private Material sobelBufferMaterial; + + private bool sobelBufferReferencesReady; + + private static Shader sobelShader; + + private static Action callbacksFromStaticMethod; + + private static bool currentlyPreloadingShader; + + [SystemInitializer(new Type[] { })] + public static void PreloadShaderReference() + { + if (currentlyPreloadingShader || sobelShader != null) + { + if (sobelShader != null) + { + SetShaderReference(sobelShader); + } + return; + } + if (LegacyShaderAPI.TryToGetPreloadedShader("Hopoo Games/Internal/SobelBuffer", out var cachedShader)) + { + SetShaderReference(cachedShader); + return; + } + AsyncOperationHandle asyncOperationHandle = Addressables.LoadAssetAsync("780f79b2a62a0df439dedf59c533eee6"); + asyncOperationHandle.Completed += delegate(AsyncOperationHandle obj) + { + SetShaderReference(obj.Result); + }; + currentlyPreloadingShader = true; + } + + private static void SetShaderReference(Shader _shader) + { + if (_shader != null) + { + sobelShader = _shader; + callbacksFromStaticMethod?.Invoke(); + callbacksFromStaticMethod = null; + currentlyPreloadingShader = false; + } + } + + private void Awake() + { + Initialize(); + } + + private void OnDestroy() + { + DestroyTemporaryAsset(sobelBufferMaterial); + sobelBufferReferencesReady = false; + } + + private void OnEnable() + { + if (!Application.isPlaying) + { + Initialize(); + } + camera.AddCommandBuffer(cameraEvent, sobelCommandBuffer); + sobelCommandBufferSubscribedEvent = cameraEvent; + } + + private void OnDisable() + { + DestroyTemporaryAsset(sobelInfoTex); + camera.RemoveCommandBuffer(sobelCommandBufferSubscribedEvent, sobelCommandBuffer); + sobelCommandBuffer.Clear(); + } + + private void OnPreRender() + { + Rebuild(); + } + + private void Initialize() + { + if (sobelShader == null) + { + callbacksFromStaticMethod = (Action)Delegate.Combine(callbacksFromStaticMethod, new Action(Initialize)); + PreloadShaderReference(); + return; + } + camera = GetComponent(); + sobelBufferMaterial = new Material(sobelShader); + sobelCommandBuffer = new CommandBuffer(); + sobelCommandBuffer.name = "Sobel Command Buffer"; + sobelBufferReferencesReady = true; + } + + private void Rebuild() + { + if (!sobelBufferReferencesReady) + { + Initialize(); + return; + } + Vector2Int vector2Int = new Vector2Int(camera.pixelWidth, camera.pixelHeight); + RenderTexture renderTexture = sobelInfoTex; + if ((bool)sobelInfoTex && new Vector2Int(sobelInfoTex.width, sobelInfoTex.height) != vector2Int) + { + DestroyTemporaryAsset(sobelInfoTex); + sobelInfoTex = null; + } + if (!sobelInfoTex && vector2Int.x > 0 && vector2Int.y > 0) + { + sobelInfoTex = new RenderTexture(vector2Int.x, vector2Int.y, 0, GraphicsFormat.R8_UNorm, 0); + sobelInfoTex.name = "Sobel Outline Information"; + } + if (renderTexture != sobelInfoTex) + { + int nameID = Shader.PropertyToID("_SobelTex"); + RenderTargetIdentifier renderTargetIdentifier = new RenderTargetIdentifier(sobelInfoTex); + RenderTargetIdentifier source = new RenderTargetIdentifier(BuiltinRenderTextureType.ResolvedDepth); + RenderTargetIdentifier renderTarget = new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget); + sobelCommandBuffer.Clear(); + sobelCommandBuffer.Blit(source, renderTargetIdentifier, sobelBufferMaterial); + sobelCommandBuffer.SetGlobalTexture(nameID, renderTargetIdentifier); + sobelCommandBuffer.SetRenderTarget(renderTarget); + } + } + + private void DestroyTemporaryAsset(UnityEngine.Object temporaryAsset) + { + if (Application.isPlaying) + { + UnityEngine.Object.Destroy(temporaryAsset); + } + else + { + UnityEngine.Object.DestroyImmediate(temporaryAsset); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/DamageIndicator.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/DamageIndicator.cs new file mode 100644 index 0000000..311d0c3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/DamageIndicator.cs @@ -0,0 +1,137 @@ +using UnityEngine; + +namespace RoR2.PostProcessing; + +public class DamageIndicator : MonoBehaviour +{ + private struct IndicatorTimestamp + { + public Run.FixedTimeStamp hitTimeStamp; + + public bool isActive; + } + + private CameraRigController cameraRigController; + + public Material mat; + + public float boxCornerRadius = 0.5f; + + public float boxFeather = 0.5f; + + public float maxboxSize = 1f; + + public float minboxSize = 0.75f; + + [Tooltip("The color of the damage indicator.")] + public Color tintColor; + + [Tooltip("X and Y are the normalized screen position, and Z is the opacity of the indicator.")] + public Vector4[] indicators = new Vector4[8]; + + private IndicatorTimestamp[] _indicatorTimestamps = new IndicatorTimestamp[8]; + + [Tooltip("The radius of the mask for the indicator. It will be scaled to fit the aspect ratio of the screen.")] + public float indicatorRadius; + + [Tooltip("The opacity of the indicator over time.")] + public AnimationCurve indicatorOpacity; + + [Min(0.01f)] + [Tooltip("The duration of the indicator. This will scale the opacity fade time.")] + public float indicatorDuration = 1f; + + [Tooltip("The feather on the indicator mask.")] + public float indicatorFeather = 0.5f; + + private float _indicatorValue; + + private bool isEnabled = true; + + private void Awake() + { + cameraRigController = GetComponentInParent(); + mat = Object.Instantiate(mat); + } + + private void OnEnable() + { + GlobalEventManager.onClientDamageNotified += OnClientDamage; + } + + public void OnDisable() + { + GlobalEventManager.onClientDamageNotified -= OnClientDamage; + } + + private float GetBoxSize(float value) + { + return Util.Remap(value, 0f, 1f, maxboxSize, minboxSize); + } + + public void OnClientDamage(DamageDealtMessage damageDealtMessage) + { + if (!(damageDealtMessage.attacker == null) && !(damageDealtMessage.victim == null) && (bool)cameraRigController && damageDealtMessage.victim == cameraRigController.localUserViewer.cachedBodyObject) + { + _indicatorValue = cameraRigController.localUserViewer.userProfile.directionalDamageIndicatorScale; + Vector3 forward = cameraRigController.transform.forward; + Vector3 position = damageDealtMessage.victim.gameObject.transform.position; + Vector3 position2 = damageDealtMessage.attacker.gameObject.transform.position; + Vector2 to = new Vector2(position.x, position.z) - new Vector2(position2.x, position2.z); + int num = Mathf.RoundToInt((0f - Vector2.SignedAngle(new Vector2(forward.x, forward.z), to) + 180f) / 45f) % 8; + _indicatorTimestamps[num].hitTimeStamp = Run.FixedTimeStamp.now; + _indicatorTimestamps[num].isActive = true; + } + } + + private void ResetIndicators() + { + for (int i = 0; i < _indicatorTimestamps.Length; i++) + { + _indicatorTimestamps[i].isActive = false; + indicators[i].z = 0f; + } + } + + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + if (Mathf.Approximately(_indicatorValue, 0f)) + { + if (isEnabled) + { + ResetIndicators(); + mat.SetVectorArray("_Indicators", indicators); + isEnabled = false; + } + Graphics.Blit(source, destination, mat); + return; + } + if (!isEnabled) + { + isEnabled = true; + } + mat.SetFloat("_BoxCornerRadius", boxCornerRadius); + mat.SetFloat("_BoxFeather", boxFeather); + mat.SetFloat("_BoxSize", GetBoxSize(_indicatorValue)); + mat.SetColor("_TintColor", tintColor); + mat.SetFloat("_IndicatorRadius", indicatorRadius); + mat.SetFloat("_IndicatorFeather", indicatorFeather); + for (int i = 0; i < _indicatorTimestamps.Length; i++) + { + if (_indicatorTimestamps[i].isActive) + { + float timeSince = _indicatorTimestamps[i].hitTimeStamp.timeSince; + if (timeSince >= indicatorDuration) + { + _indicatorTimestamps[i].isActive = false; + } + else + { + indicators[i].z = Mathf.Clamp(indicatorOpacity.Evaluate(timeSince / indicatorDuration), 0f, 1f); + } + } + } + mat.SetVectorArray("_Indicators", indicators); + Graphics.Blit(source, destination, mat); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/HopooPostProcess.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/HopooPostProcess.cs new file mode 100644 index 0000000..5a7e204 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/HopooPostProcess.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +namespace RoR2.PostProcessing; + +[ExecuteInEditMode] +public class HopooPostProcess : MonoBehaviour +{ + public Material mat; + + private void Start() + { + } + + [ImageEffectOpaque] + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + Graphics.Blit(source, destination, mat); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamage.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamage.cs new file mode 100644 index 0000000..4b2641f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamage.cs @@ -0,0 +1,127 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +namespace RoR2.PostProcessing; + +public class ScreenDamage : MonoBehaviour +{ + private CameraRigController cameraRigController; + + private PostProcessLayer postProcessLayer; + + private ScreenDamagePP postProcessSettings; + + [Header("Debug values")] + public bool useDebugValues; + + public float debugTintValue; + + public float debugDesatValue; + + public float debugDistortionValue; + + [Header("Game-wide limits")] + public float DistortionScale = 1f; + + public float DistortionPower = 1f; + + public float DesaturationScale = 1f; + + public float DesaturationPower = 1f; + + public float TintScale = 1f; + + public float TintPower = 1f; + + public float debugHealthPercentage; + + private float healthPercentage = 1f; + + private const float hitTintDecayTime = 0.6f; + + private const float hitTintScale = 1.6f; + + private const float deathWeight = 2f; + + private float oldDistortionStrength; + + private float oldDesaturationStrength; + + private float oldTintStrength; + + private ScreenDamageCalculatorDefault screenDamageCalculatorDefault = new ScreenDamageCalculatorDefault(); + + private ScreenDamageCalculator workingScreenDamageCalculator; + + private void Awake() + { + InitPostProcessSettingsVars(); + } + + private void OnEnable() + { + InitPostProcessSettingsVars(); + } + + private void InitPostProcessSettingsVars() + { + if (!(postProcessSettings != null)) + { + cameraRigController = GetComponentInParent(); + postProcessLayer = GetComponent(); + GetComponentInChildren().profile.TryGetSettings(out postProcessSettings); + if ((bool)postProcessSettings) + { + oldDistortionStrength = postProcessSettings.DistortionStrength.value; + oldDesaturationStrength = postProcessSettings.DesaturationStrength.value; + oldTintStrength = postProcessSettings.TintStrength.value; + } + } + } + + public void Update() + { + InitPostProcessSettingsVars(); + if ((bool)cameraRigController) + { + if ((bool)cameraRigController.target) + { + HealthComponent component = cameraRigController.target.GetComponent(); + if (component != null && component.screenDamageCalculator != null) + { + workingScreenDamageCalculator = component.screenDamageCalculator; + } + else + { + workingScreenDamageCalculator = screenDamageCalculatorDefault; + } + workingScreenDamageCalculator.CalculateScreenDamage(this, component); + } + else + { + workingScreenDamageCalculator = screenDamageCalculatorDefault; + } + float num = (SettingsConVars.enableScreenDistortion.value ? DistortionScale : 0f); + ScreenDamageData screenDamageData = workingScreenDamageCalculator.screenDamageData; + postProcessSettings.DistortionStrength.Override(screenDamageData.distortionStrength * num); + postProcessSettings.DesaturationStrength.Override(screenDamageData.desaturationStrength); + postProcessSettings.TintStrength.Override(screenDamageData.tintStrength); + } + else + { + postProcessSettings.DistortionStrength.Override(0f); + postProcessSettings.DesaturationStrength.Override(0f); + postProcessSettings.TintStrength.Override(0f); + } + float value = postProcessSettings.DistortionStrength.value; + float value2 = postProcessSettings.DesaturationStrength.value; + float value3 = postProcessSettings.TintStrength.value; + if (!Mathf.Approximately(oldDistortionStrength, value) || !Mathf.Approximately(oldDesaturationStrength, value2) || !Mathf.Approximately(oldTintStrength, value3)) + { + postProcessLayer.OnVolumeSettingsChanged(); + oldDistortionStrength = postProcessSettings.DistortionStrength.value; + oldDesaturationStrength = postProcessSettings.DesaturationStrength.value; + oldTintStrength = postProcessSettings.TintStrength.value; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculator.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculator.cs new file mode 100644 index 0000000..8480d3a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculator.cs @@ -0,0 +1,12 @@ +namespace RoR2.PostProcessing; + +public abstract class ScreenDamageCalculator +{ + public static int TypeCounter; + + public abstract ScreenDamageData screenDamageData { get; } + + public abstract void CalculateScreenDamage(ScreenDamage screenDamage, HealthComponent healthComponent); + + public abstract void End(); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorDefault.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorDefault.cs new file mode 100644 index 0000000..ad360d3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorDefault.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace RoR2.PostProcessing; + +public class ScreenDamageCalculatorDefault : ScreenDamageCalculator +{ + private const float deathWeight = 0.5f; + + private const float hitTintDecayTime = 0.6f; + + private const float hitTintScale = 0.9f; + + private float healthPercentage; + + private float totalStrength; + + private float hitTint; + + private ScreenDamageData _screenDamageData = new ScreenDamageData(Color.red, 0f, 0f, 0f, _combineAdditively: false); + + public override ScreenDamageData screenDamageData => _screenDamageData; + + public bool combineAdditively => false; + + public override void CalculateScreenDamage(ScreenDamage screenDamage, HealthComponent targetHealthComponent) + { + totalStrength = 0.5f; + hitTint = 0f; + if ((bool)targetHealthComponent) + { + healthPercentage = Mathf.Clamp(targetHealthComponent.health / targetHealthComponent.fullHealth, 0f, 1f); + hitTint = Mathf.Clamp01(1f - targetHealthComponent.timeSinceLastHit / 0.6f) * 0.9f; + if (targetHealthComponent.health <= 0f) + { + totalStrength = 0f; + } + } + if (screenDamage.debugHealthPercentage != 0f) + { + healthPercentage = screenDamage.debugHealthPercentage; + } + _screenDamageData.distortionStrength = totalStrength * screenDamage.DistortionScale * Mathf.Pow(1f - healthPercentage, screenDamage.DistortionPower); + _screenDamageData.desaturationStrength = totalStrength * screenDamage.DesaturationScale * Mathf.Pow(1f - healthPercentage, screenDamage.DesaturationPower); + _screenDamageData.tintStrength = totalStrength * screenDamage.TintScale * (Mathf.Pow(1f - healthPercentage, screenDamage.TintPower) + hitTint); + } + + public override void End() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorDisabledSkills.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorDisabledSkills.cs new file mode 100644 index 0000000..599c343 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorDisabledSkills.cs @@ -0,0 +1,75 @@ +using UnityEngine; + +namespace RoR2.PostProcessing; + +public class ScreenDamageCalculatorDisabledSkills : ScreenDamageCalculator +{ + private const float deathWeight = 0.5f; + + private const float hitTintDecayTime = 0.6f; + + private const float hitTintScale = 0.9f; + + private const float deSaturationBase = 0.8f; + + private const float tintBase = 0.03f; + + private const float tintMaximum = 0.17f; + + private float healthPercentage; + + private float totalStrength; + + private float hitTint; + + private ScreenDamageData _screenDamageData = new ScreenDamageData(Color.grey, 0f, 0.7f, 0.3f, _combineAdditively: false); + + public override ScreenDamageData screenDamageData => _screenDamageData; + + public bool combineAdditively => false; + + public override void CalculateScreenDamage(ScreenDamage screenDamage, HealthComponent targetHealthComponent) + { + totalStrength = 0.5f; + hitTint = 0f; + if ((bool)targetHealthComponent) + { + healthPercentage = Mathf.Clamp(targetHealthComponent.health / targetHealthComponent.fullHealth, 0f, 1f); + hitTint = Mathf.Clamp01(1f - targetHealthComponent.timeSinceLastHit / 0.6f) * 0.9f; + if (targetHealthComponent.health <= 0f) + { + totalStrength = 0f; + } + } + if (screenDamage.debugHealthPercentage != 0f) + { + healthPercentage = screenDamage.debugHealthPercentage; + } + float distortionStrength = totalStrength * screenDamage.DistortionScale * Mathf.Pow(1f - healthPercentage, screenDamage.DistortionPower); + if (screenDamage.useDebugValues) + { + distortionStrength = screenDamage.debugDistortionValue; + } + _screenDamageData.distortionStrength = distortionStrength; + distortionStrength = 0.8f; + if (screenDamage.useDebugValues) + { + distortionStrength = screenDamage.debugDesatValue; + } + _screenDamageData.desaturationStrength = distortionStrength; + distortionStrength = 0.03f; + distortionStrength += (totalStrength * screenDamage.TintScale + 0.2f) * (Mathf.Pow(1f - healthPercentage, screenDamage.TintPower) + hitTint); + distortionStrength = Mathf.Min(distortionStrength, 0.17f); + if (screenDamage.useDebugValues) + { + distortionStrength = screenDamage.debugTintValue; + } + _screenDamageData.tintStrength = distortionStrength; + ScreenDamagePPRenderer.ExtendTemporaryProps(); + } + + public override void End() + { + ScreenDamagePPRenderer.ClearTemporaryProps(this); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorSojourn.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorSojourn.cs new file mode 100644 index 0000000..d7d4b6a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageCalculatorSojourn.cs @@ -0,0 +1,78 @@ +using UnityEngine; + +namespace RoR2.PostProcessing; + +public class ScreenDamageCalculatorSojourn : ScreenDamageCalculator +{ + private float totalStrength; + + private float hitTint; + + private const float deathWeight = 0.5f; + + private const float hitTintDecayTime = 0.6f; + + private const float hitTintScale = 1.6f; + + private float healthPercentage; + + private ScreenDamageData _screenDamageData = new ScreenDamageData(); + + public float minimumDamage = 0.2f; + + public float maximumDamage = 0.8f; + + public float duration = 4f; + + public bool _combineAdditively; + + private float timeStarted; + + private bool initialized; + + public override ScreenDamageData screenDamageData => _screenDamageData; + + public override void CalculateScreenDamage(ScreenDamage screenDamage, HealthComponent targetHealthComponent) + { + if (!initialized) + { + Initialize(); + } + totalStrength = 0.5f; + hitTint = 0f; + float num = (Time.time - timeStarted) % duration / duration; + if (num > 0.5f) + { + num = 0.5f - (num - 0.5f); + } + num /= 0.5f; + healthPercentage = Mathf.Lerp(minimumDamage, maximumDamage, num); + if (screenDamage.debugHealthPercentage != 0f) + { + healthPercentage = screenDamage.debugHealthPercentage; + } + _screenDamageData.distortionStrength = totalStrength * screenDamage.DistortionScale * Mathf.Pow(healthPercentage, screenDamage.DistortionPower); + _screenDamageData.desaturationStrength = totalStrength * screenDamage.DesaturationScale * Mathf.Pow(healthPercentage, screenDamage.DesaturationPower); + _screenDamageData.tintStrength = totalStrength * screenDamage.TintScale * (Mathf.Pow(healthPercentage, screenDamage.TintPower) + hitTint); + ScreenDamagePPRenderer.ExtendTemporaryProps(); + } + + private void Initialize() + { + initialized = true; + timeStarted = Time.time; + if (_screenDamageData.tintColor == default(Color)) + { + _screenDamageData.IntendedTintColor = Color.yellow; + } + ScreenDamagePPRenderer.SetTemporaryProps(this, _screenDamageData.colorParameter, null, _screenDamageData.combineAdditively); + } + + public override void End() + { + if (initialized) + { + ScreenDamagePPRenderer.ClearTemporaryProps(this); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageData.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageData.cs new file mode 100644 index 0000000..d5ae75a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/ScreenDamageData.cs @@ -0,0 +1,54 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +namespace RoR2.PostProcessing; + +[Serializable] +public class ScreenDamageData +{ + public Color IntendedTintColor; + + public float distortionStrength; + + public float desaturationStrength; + + public float tintStrength; + + public bool combineAdditively; + + public Color tintColor + { + get + { + if (combineAdditively) + { + return IntendedTintColor; + } + return (Color)Vector4.one - IntendedTintColor; + } + } + + public ColorParameter colorParameter => new ColorParameter + { + value = tintColor + }; + + public ScreenDamageData(Color _tintColor, float _distortionStrength, float _desatStrength, float _tintStrength, bool _combineAdditively) + { + IntendedTintColor = _tintColor; + distortionStrength = _distortionStrength; + desaturationStrength = _desatStrength; + tintStrength = _tintStrength; + combineAdditively = _combineAdditively; + } + + public ScreenDamageData() + { + IntendedTintColor = Color.red; + distortionStrength = 0f; + desaturationStrength = 0f; + tintStrength = 0f; + combineAdditively = false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.PostProcessing/VisionLimitEffect.cs b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/VisionLimitEffect.cs new file mode 100644 index 0000000..b0fd17d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.PostProcessing/VisionLimitEffect.cs @@ -0,0 +1,118 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace RoR2.PostProcessing; + +[RequireComponent(typeof(Camera))] +public class VisionLimitEffect : MonoBehaviour +{ + private static class ShaderParamsIDs + { + public static int origin = Shader.PropertyToID("_Origin"); + + public static int rangeStart = Shader.PropertyToID("_RangeStart"); + + public static int rangeEnd = Shader.PropertyToID("_RangeEnd"); + + public static int color = Shader.PropertyToID("_Color"); + } + + public CameraRigController cameraRigController; + + private Camera camera; + + private float desiredVisionDistance = float.PositiveInfinity; + + private CommandBuffer commandBuffer; + + private Material material; + + private Vector3 lastKnownTargetPosition; + + private float currentAlpha; + + private float alphaVelocity; + + private float currentVisionDistance; + + private float currentVisionDistanceVelocity; + + private void Awake() + { + camera = GetComponent(); + commandBuffer = new CommandBuffer(); + commandBuffer.name = "VisionLimitEffect"; + Shader shader = LegacyShaderAPI.Find("Hopoo Games/Internal/VisionLimit"); + material = new Material(shader); + material.name = "VisionLimitEffectMaterial"; + } + + private void OnDestroy() + { + DestroyTemporaryAsset(material); + commandBuffer = null; + camera = null; + } + + private void OnEnable() + { + camera.AddCommandBuffer(CameraEvent.AfterImageEffectsOpaque, commandBuffer); + } + + private void OnDisable() + { + camera.RemoveCommandBuffer(CameraEvent.AfterImageEffectsOpaque, commandBuffer); + } + + private void OnPreCull() + { + UpdateCommandBuffer(); + } + + private void LateUpdate() + { + Transform transform = (cameraRigController.target ? cameraRigController.target.transform : null); + CharacterBody targetBody = cameraRigController.targetBody; + if ((bool)transform) + { + lastKnownTargetPosition = transform.position; + } + desiredVisionDistance = (targetBody ? targetBody.visionDistance : float.PositiveInfinity); + float target = 0f; + float target2 = 4000f; + if (desiredVisionDistance != float.PositiveInfinity) + { + target = 1f; + target2 = desiredVisionDistance; + } + currentAlpha = Mathf.SmoothDamp(currentAlpha, target, ref alphaVelocity, 0.2f, float.PositiveInfinity, Time.deltaTime); + currentVisionDistance = Mathf.SmoothDamp(currentVisionDistance, target2, ref currentVisionDistanceVelocity, 0.2f, float.PositiveInfinity, Time.deltaTime); + } + + private void UpdateCommandBuffer() + { + commandBuffer.Clear(); + if (!(currentAlpha <= 0f)) + { + float num = Mathf.Max(0f, currentVisionDistance * 0.5f); + float value = Mathf.Max(num + 0.01f, currentVisionDistance); + material.SetVector(ShaderParamsIDs.origin, lastKnownTargetPosition); + material.SetFloat(ShaderParamsIDs.rangeStart, num); + material.SetFloat(ShaderParamsIDs.rangeEnd, value); + material.SetColor(ShaderParamsIDs.color, new Color(0f, 0f, 0f, currentAlpha)); + commandBuffer.Blit(null, BuiltinRenderTextureType.CurrentActive, material); + } + } + + private void DestroyTemporaryAsset(Object temporaryAsset) + { + if (Application.isPlaying) + { + Object.Destroy(temporaryAsset); + } + else + { + Object.DestroyImmediate(temporaryAsset); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/AssignTeamFilterToTeamComponent.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/AssignTeamFilterToTeamComponent.cs new file mode 100644 index 0000000..8b9c5c1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/AssignTeamFilterToTeamComponent.cs @@ -0,0 +1,21 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(HealthComponent))] +public class AssignTeamFilterToTeamComponent : MonoBehaviour +{ + private void Start() + { + if (NetworkServer.active) + { + TeamComponent component = GetComponent(); + TeamFilter component2 = GetComponent(); + if ((bool)component2 && (bool)component) + { + component.teamIndex = component2.teamIndex; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/BoomerangProjectile.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/BoomerangProjectile.cs new file mode 100644 index 0000000..0dbaca7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/BoomerangProjectile.cs @@ -0,0 +1,264 @@ +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class BoomerangProjectile : NetworkBehaviour, IProjectileImpactBehavior +{ + private enum BoomerangState + { + FlyOut, + Transition, + FlyBack, + NetworkClientCatchup + } + + public float travelSpeed = 40f; + + public float charge; + + public float transitionDuration; + + private float maxFlyStopwatch; + + public GameObject impactSpark; + + public GameObject crosshairPrefab; + + public bool canHitCharacters; + + public bool canHitWorld; + + private ProjectileController projectileController; + + [SyncVar] + private BoomerangState boomerangState; + + private Transform ownerTransform; + + private ProjectileDamage projectileDamage; + + private Rigidbody rigidbody; + + private float stopwatch; + + private float fireAge; + + private float fireFrequency; + + public float distanceMultiplier = 2f; + + public UnityEvent onFlyBack; + + [Tooltip("Allows the server and client side boomerangs to idle harmlessly/invisibly for up to 1 second while the rest of the boomerangs from other clients have time to finish their flight.")] + public bool EnableNetworkClientCatchup; + + private bool setScale; + + private float networkCatchupTimer = -1f; + + private float networkCatchupDuration = 1f; + + public bool isStunAndPierce; + + public BoomerangState NetworkboomerangState + { + get + { + return boomerangState; + } + [param: In] + set + { + ulong newValueAsUlong = (ulong)value; + ulong fieldValueAsUlong = (ulong)boomerangState; + SetSyncVarEnum(value, newValueAsUlong, ref boomerangState, fieldValueAsUlong, 1u); + } + } + + private void Awake() + { + rigidbody = GetComponent(); + projectileController = GetComponent(); + projectileDamage = GetComponent(); + if ((bool)projectileController && (bool)projectileController.owner) + { + ownerTransform = projectileController.owner.transform; + } + maxFlyStopwatch = charge * distanceMultiplier; + } + + private void Start() + { + float num = charge * 7f; + if (num < 1f) + { + num = 1f; + } + Vector3 localScale = new Vector3(num * base.transform.localScale.x, num * base.transform.localScale.y, num * base.transform.localScale.z); + base.transform.localScale = localScale; + base.gameObject.GetComponent().ghost.transform.localScale = localScale; + GetComponent().damageCoefficient *= num; + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (canHitWorld) + { + NetworkboomerangState = BoomerangState.FlyBack; + onFlyBack?.Invoke(); + EffectManager.SimpleImpactEffect(impactSpark, impactInfo.estimatedPointOfImpact, -base.transform.forward, transmit: true); + } + } + + private bool Reel() + { + return (projectileController.owner.transform.position - base.transform.position).magnitude <= 2f; + } + + public void FixedUpdate() + { + bool active = NetworkServer.active; + if (active) + { + if (!setScale) + { + setScale = true; + } + if (!projectileController.owner) + { + Object.Destroy(base.gameObject); + return; + } + } + switch (boomerangState) + { + case BoomerangState.FlyOut: + if (active) + { + rigidbody.velocity = travelSpeed * base.transform.forward; + stopwatch += Time.fixedDeltaTime; + if (stopwatch >= maxFlyStopwatch) + { + stopwatch = 0f; + NetworkboomerangState = BoomerangState.Transition; + } + } + break; + case BoomerangState.Transition: + if (active) + { + stopwatch += Time.fixedDeltaTime; + float num = stopwatch / transitionDuration; + Vector3 vector = CalculatePullDirection(); + rigidbody.velocity = Vector3.Lerp(travelSpeed * base.transform.forward, travelSpeed * vector, num); + if (num >= 1f) + { + NetworkboomerangState = BoomerangState.FlyBack; + onFlyBack?.Invoke(); + } + } + break; + case BoomerangState.FlyBack: + { + bool num2 = Reel(); + if (active) + { + canHitWorld = false; + Vector3 vector2 = CalculatePullDirection(); + rigidbody.velocity = travelSpeed * vector2; + } + if (!num2) + { + break; + } + if (EnableNetworkClientCatchup) + { + projectileController.DisconnectFromGhost(); + if (active) + { + networkCatchupTimer = networkCatchupDuration; + NetworkboomerangState = BoomerangState.NetworkClientCatchup; + } + } + else if (active) + { + Object.Destroy(base.gameObject); + } + break; + } + case BoomerangState.NetworkClientCatchup: + if (!active) + { + if (Reel()) + { + projectileController.DisconnectFromGhost(); + } + break; + } + networkCatchupTimer -= Time.fixedDeltaTime; + if (networkCatchupTimer <= 0f) + { + Object.Destroy(base.gameObject); + } + break; + } + Vector3 CalculatePullDirection() + { + if ((bool)projectileController.owner) + { + return (projectileController.owner.transform.position - base.transform.position).normalized; + } + return base.transform.forward; + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write((int)boomerangState); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write((int)boomerangState); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + boomerangState = (BoomerangState)reader.ReadInt32(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + boomerangState = (BoomerangState)reader.ReadInt32(); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/CleaverProjectile.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/CleaverProjectile.cs new file mode 100644 index 0000000..f5a7030 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/CleaverProjectile.cs @@ -0,0 +1,408 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; +using UnityEngine.Serialization; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class CleaverProjectile : NetworkBehaviour, IProjectileImpactBehavior +{ + private enum BoomerangState + { + FlyOut, + Transition, + FlyBack, + Stopped + } + + public float travelSpeed = 40f; + + public float charge; + + public float transitionDuration; + + private float maxFlyStopwatch; + + public GameObject impactSpark; + + public GameObject returnImpactSpark; + + public GameObject crosshairPrefab; + + public bool canHitCharacters; + + public bool canHitWorld; + + public bool returnOnHitWorldOrHover; + + public ProjectileController projectileController; + + [SyncVar] + private BoomerangState boomerangState; + + private Transform ownerTransform; + + private ProjectileDamage projectileDamage; + + private Rigidbody rigidbody; + + private float stopwatch; + + private float fireAge; + + private float fireFrequency; + + [FormerlySerializedAs("distanceMultiplier")] + public float travelTime = 2f; + + public UnityEvent onFlyBack; + + private bool setScale; + + private bool recallDamageFired; + + private float stoppedStopwatch = 3f; + + private ChefController chefController; + + private ushort predictionId; + + private bool recalled; + + private bool hasEffectiveAuthority; + + private bool disableOnRcall_ReelingCache; + + public Collider[] disableOnRecall; + + private static int kCmdCmdDestroyAndCleanup; + + public BoomerangState NetworkboomerangState + { + get + { + return boomerangState; + } + [param: In] + set + { + ulong newValueAsUlong = (ulong)value; + ulong fieldValueAsUlong = (ulong)boomerangState; + SetSyncVarEnum(value, newValueAsUlong, ref boomerangState, fieldValueAsUlong, 1u); + } + } + + private void Awake() + { + rigidbody = GetComponent(); + projectileController = GetComponent(); + projectileDamage = GetComponent(); + maxFlyStopwatch = travelTime; + } + + private void Start() + { + if ((bool)projectileController) + { + predictionId = projectileController.predictionId; + if ((bool)projectileController.owner) + { + ownerTransform = projectileController.owner.transform; + chefController = projectileController.owner.GetComponent(); + if ((bool)chefController) + { + chefController.AddLocalProjectileReference(predictionId, this); + if (base.hasAuthority && !NetworkServer.active && chefController.TryRetrieveCachedProjectileFireInfo(out var fireProjectileInfo)) + { + ApplyCachedFireProjectileInfo(fireProjectileInfo); + } + } + } + } + hasEffectiveAuthority = Util.HasEffectiveAuthority(chefController.gameObject); + } + + private void ApplyCachedFireProjectileInfo(FireProjectileInfo fireProjectileInfo) + { + ProjectileDamage component = GetComponent(); + TeamFilter component2 = GetComponent(); + ProjectileSimple component3 = GetComponent(); + if ((bool)component2) + { + component2.teamIndex = TeamComponent.GetObjectTeam(fireProjectileInfo.owner); + } + if (fireProjectileInfo.useSpeedOverride && (bool)component3) + { + component3.desiredForwardSpeed = fireProjectileInfo.speedOverride; + } + if ((bool)component) + { + component.damage = fireProjectileInfo.damage; + component.force = fireProjectileInfo.force; + component.crit = fireProjectileInfo.crit; + component.damageColorIndex = fireProjectileInfo.damageColorIndex; + if (fireProjectileInfo.damageTypeOverride.HasValue) + { + component.damageType = fireProjectileInfo.damageTypeOverride.Value; + } + } + projectileController.DispatchOnInitialized(); + } + + private void OnEnable() + { + recalled = false; + recallDamageFired = false; + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (!canHitWorld) + { + return; + } + if (impactInfo.collider.gameObject.layer == LayerIndex.world.intVal) + { + if (returnOnHitWorldOrHover) + { + NetworkboomerangState = BoomerangState.FlyBack; + } + else + { + NetworkboomerangState = BoomerangState.Stopped; + } + } + if (boomerangState != BoomerangState.Stopped) + { + EffectManager.SimpleImpactEffect(recalled ? returnImpactSpark : impactSpark, impactInfo.estimatedPointOfImpact, -base.transform.forward, transmit: true); + } + } + + private bool Reel() + { + Vector3 vector = projectileController.owner.transform.position - base.transform.position; + _ = vector.normalized; + float magnitude = vector.magnitude; + if (!chefController) + { + chefController = projectileController.owner.GetComponent(); + } + return magnitude <= 2f; + } + + public void FixedUpdate() + { + if (!hasEffectiveAuthority) + { + return; + } + if (!setScale) + { + setScale = true; + } + if (!projectileController.owner) + { + Object.Destroy(base.gameObject); + return; + } + if (!chefController) + { + chefController = projectileController.owner.GetComponent(); + } + recalled = recalled || chefController.recallCleaver || boomerangState == BoomerangState.FlyBack; + if ((bool)chefController && recalled && boomerangState != BoomerangState.Transition) + { + NetworkboomerangState = BoomerangState.FlyBack; + } + if (returnOnHitWorldOrHover && boomerangState == BoomerangState.Stopped) + { + NetworkboomerangState = BoomerangState.FlyBack; + recalled = true; + } + if (!recalled) + { + ToggleThrowOnlyObjects(isReeling: false); + switch (boomerangState) + { + case BoomerangState.FlyOut: + rigidbody.velocity = travelSpeed * base.transform.forward; + stopwatch += Time.fixedDeltaTime; + if (stopwatch >= maxFlyStopwatch) + { + stopwatch = 0f; + NetworkboomerangState = BoomerangState.Stopped; + } + break; + case BoomerangState.Transition: + { + stopwatch += Time.fixedDeltaTime; + float num = stopwatch / transitionDuration; + Vector3 vector = CalculatePullDirection(); + rigidbody.velocity = Vector3.Lerp(travelSpeed * base.transform.forward, travelSpeed * vector, num); + if (num >= 0.1f) + { + NetworkboomerangState = BoomerangState.FlyBack; + onFlyBack?.Invoke(); + } + break; + } + case BoomerangState.Stopped: + chefController = projectileController.owner.GetComponent(); + rigidbody.velocity = new Vector3(0f, 0f, 0f); + stopwatch += Time.deltaTime; + if (stopwatch > stoppedStopwatch) + { + CallCmdDestroyAndCleanup(); + } + break; + case BoomerangState.FlyBack: + break; + } + return; + } + ToggleThrowOnlyObjects(isReeling: true); + if (!recallDamageFired) + { + rigidbody.velocity = new Vector3(0f, 0f, 0f); + GetComponent().ResetOverlapAttack(); + projectileDamage.damage *= 1.5f; + recallDamageFired = true; + } + bool num2 = Reel(); + Vector3 vector2 = CalculatePullDirection(); + rigidbody.velocity = travelSpeed * vector2; + if (num2) + { + if (chefController != null) + { + chefController.NetworkcatchDirtied = true; + } + CallCmdDestroyAndCleanup(); + } + } + + private void ToggleThrowOnlyObjects(bool isReeling) + { + if (disableOnRcall_ReelingCache != isReeling) + { + int num = disableOnRecall.Length; + for (int i = 0; i < num; i++) + { + disableOnRecall[i].enabled = !isReeling; + } + disableOnRcall_ReelingCache = isReeling; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Command] + public void CmdDestroyAndCleanup() + { + Object.Destroy(base.gameObject); + } + + private Vector3 CalculatePullDirection() + { + if ((bool)projectileController.owner) + { + return (projectileController.owner.transform.position - base.transform.position).normalized; + } + return base.transform.forward; + } + + private void OnDestroy() + { + if ((bool)chefController) + { + chefController.RemoveLocalProjectileReference(predictionId); + } + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdDestroyAndCleanup(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdDestroyAndCleanup called on client."); + } + else + { + ((CleaverProjectile)obj).CmdDestroyAndCleanup(); + } + } + + public void CallCmdDestroyAndCleanup() + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdDestroyAndCleanup called on server."); + return; + } + if (base.isServer) + { + CmdDestroyAndCleanup(); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdDestroyAndCleanup); + networkWriter.Write(GetComponent().netId); + SendCommandInternal(networkWriter, 0, "CmdDestroyAndCleanup"); + } + + static CleaverProjectile() + { + kCmdCmdDestroyAndCleanup = 978502080; + NetworkBehaviour.RegisterCommandDelegate(typeof(CleaverProjectile), kCmdCmdDestroyAndCleanup, InvokeCmdCmdDestroyAndCleanup); + NetworkCRC.RegisterBehaviour("CleaverProjectile", 0); + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write((int)boomerangState); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write((int)boomerangState); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + boomerangState = (BoomerangState)reader.ReadInt32(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + boomerangState = (BoomerangState)reader.ReadInt32(); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/DaggerController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/DaggerController.cs new file mode 100644 index 0000000..a6f2ca3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/DaggerController.cs @@ -0,0 +1,97 @@ +using System.Collections.ObjectModel; +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(Rigidbody))] +public class DaggerController : MonoBehaviour +{ + private new Transform transform; + + private Rigidbody rigidbody; + + public Transform target; + + public float acceleration; + + public float delayTimer; + + public float giveupTimer = 8f; + + public float deathTimer = 10f; + + private float timer; + + public float turbulence; + + private bool hasPlayedSound; + + private void Awake() + { + transform = base.transform; + rigidbody = GetComponent(); + rigidbody.AddRelativeForce(Random.insideUnitSphere * 50f); + } + + private void FixedUpdate() + { + timer += Time.fixedDeltaTime; + if (timer < giveupTimer) + { + if ((bool)target) + { + Vector3 vector = target.transform.position - transform.position; + if (vector != Vector3.zero) + { + transform.rotation = Util.QuaternionSafeLookRotation(vector); + } + if (timer >= delayTimer) + { + rigidbody.AddForce(transform.forward * acceleration); + if (!hasPlayedSound) + { + Util.PlaySound("Play_item_proc_dagger_fly", base.gameObject); + hasPlayedSound = true; + } + } + } + } + else + { + rigidbody.useGravity = true; + } + if (!target) + { + target = FindTarget(); + } + else + { + HealthComponent component = target.GetComponent(); + if ((bool)component && !component.alive) + { + target = FindTarget(); + } + } + if (timer > deathTimer) + { + Object.Destroy(base.gameObject); + } + } + + private Transform FindTarget() + { + ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(TeamIndex.Monster); + float num = 99999f; + Transform result = null; + for (int i = 0; i < teamMembers.Count; i++) + { + float num2 = Vector3.SqrMagnitude(teamMembers[i].transform.position - transform.position); + if (num2 < num) + { + num = num2; + result = teamMembers[i].transform; + } + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/DeathProjectile.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/DeathProjectile.cs new file mode 100644 index 0000000..e4f1711 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/DeathProjectile.cs @@ -0,0 +1,135 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileDamage))] +[RequireComponent(typeof(HealthComponent))] +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileStickOnImpact))] +public class DeathProjectile : MonoBehaviour +{ + private ProjectileStickOnImpact projectileStickOnImpactController; + + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private HealthComponent healthComponent; + + public GameObject OnKillTickEffect; + + public TeamIndex teamIndex; + + public string activeSoundLoopString; + + public string exitSoundString; + + private float duration; + + private float fixedAge; + + public float baseDuration = 8f; + + public float radius = 500f; + + public GameObject rotateObject; + + private bool doneWithRemovalEvents; + + public float removalTime = 1f; + + private bool shouldStopSound; + + private void Awake() + { + projectileStickOnImpactController = GetComponent(); + projectileController = GetComponent(); + projectileDamage = GetComponent(); + healthComponent = GetComponent(); + duration = baseDuration; + fixedAge = 0f; + } + + private void FixedUpdate() + { + fixedAge += Time.deltaTime; + if (duration > 0f) + { + if (!(fixedAge >= 1f)) + { + return; + } + if (projectileStickOnImpactController.stuck) + { + if ((bool)projectileController.owner) + { + RotateDoll(Random.Range(90f, 180f)); + SpawnTickEffect(); + if (NetworkServer.active) + { + DamageInfo damageInfo = new DamageInfo + { + attacker = projectileController.owner, + crit = projectileDamage.crit, + damage = projectileDamage.damage, + position = base.transform.position, + procCoefficient = projectileController.procCoefficient, + damageType = projectileDamage.damageType, + damageColorIndex = projectileDamage.damageColorIndex + }; + HealthComponent victim = healthComponent; + DamageReport damageReport = new DamageReport(damageInfo, victim, damageInfo.damage, healthComponent.combinedHealth); + GlobalEventManager.instance.OnCharacterDeath(damageReport); + } + } + duration -= 1f; + } + fixedAge = 0f; + } + else + { + if (!doneWithRemovalEvents) + { + doneWithRemovalEvents = true; + rotateObject.GetComponent().enabled = true; + } + if (fixedAge >= removalTime) + { + Util.PlaySound(exitSoundString, base.gameObject); + shouldStopSound = false; + Object.Destroy(base.gameObject); + } + } + } + + private void OnDisable() + { + if (shouldStopSound) + { + Util.PlaySound(exitSoundString, base.gameObject); + shouldStopSound = false; + } + } + + public void SpawnTickEffect() + { + EffectData effectData = new EffectData + { + origin = base.transform.position, + rotation = Quaternion.identity + }; + EffectManager.SpawnEffect(OnKillTickEffect, effectData, transmit: false); + } + + public void PlayStickSoundLoop() + { + Util.PlaySound(activeSoundLoopString, base.gameObject); + shouldStopSound = true; + } + + public void RotateDoll(float rotationAmount) + { + rotateObject.transform.Rotate(new Vector3(0f, 0f, rotationAmount)); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/EngiMineGhostController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/EngiMineGhostController.cs new file mode 100644 index 0000000..bc0f1f4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/EngiMineGhostController.cs @@ -0,0 +1,47 @@ +using EntityStates.Engi.Mine; +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileGhostController))] +public class EngiMineGhostController : MonoBehaviour +{ + private ProjectileGhostController projectileGhostController; + + private EntityStateMachine armingStateMachine; + + [Tooltip("Child object which will be enabled if the projectile is armed.")] + public GameObject stickIndicator; + + private bool cachedArmed; + + private void Awake() + { + projectileGhostController = GetComponent(); + stickIndicator.SetActive(value: false); + } + + private void Start() + { + Transform authorityTransform = projectileGhostController.authorityTransform; + if ((bool)authorityTransform) + { + armingStateMachine = EntityStateMachine.FindByCustomName(authorityTransform.gameObject, "Arming"); + } + } + + private bool IsArmed() + { + return ((armingStateMachine?.state as BaseMineArmingState)?.damageScale ?? 0f) > 1f; + } + + private void FixedUpdate() + { + bool flag = IsArmed(); + if (flag != cachedArmed) + { + cachedArmed = flag; + stickIndicator.SetActive(flag); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/FireProjectileInfo.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/FireProjectileInfo.cs new file mode 100644 index 0000000..fbe0769 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/FireProjectileInfo.cs @@ -0,0 +1,70 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public struct FireProjectileInfo +{ + public GameObject projectilePrefab; + + public Vector3 position; + + public Quaternion rotation; + + public GameObject owner; + + public GameObject target; + + public bool useSpeedOverride; + + private float _speedOverride; + + public bool useFuseOverride; + + private float _fuseOverride; + + public float damage; + + public float force; + + public bool crit; + + public DamageColorIndex damageColorIndex; + + public ProcChainMask procChainMask; + + public DamageTypeCombo? damageTypeOverride; + + public float speedOverride + { + get + { + if (!useSpeedOverride) + { + return -1f; + } + return _speedOverride; + } + set + { + useSpeedOverride = value != -1f; + _speedOverride = value; + } + } + + public float fuseOverride + { + get + { + if (!useFuseOverride) + { + return -1f; + } + return _fuseOverride; + } + set + { + useFuseOverride = value != -1f; + _fuseOverride = value; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/GatewayProjectileController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/GatewayProjectileController.cs new file mode 100644 index 0000000..d19e5d4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/GatewayProjectileController.cs @@ -0,0 +1,162 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileTargetComponent))] +public class GatewayProjectileController : NetworkBehaviour, IInteractable +{ + private ProjectileController projectileController; + + private ProjectileTargetComponent projectileTargetComponent; + + [SyncVar(hook = "SetLinkedObject")] + private GameObject linkedObject; + + private GatewayProjectileController linkedGatewayProjectileController; + + private NetworkInstanceId ___linkedObjectNetId; + + public GameObject NetworklinkedObject + { + get + { + return linkedObject; + } + [param: In] + set + { + if (NetworkServer.localClientActive && !base.syncVarHookGuard) + { + base.syncVarHookGuard = true; + SetLinkedObject(value); + base.syncVarHookGuard = false; + } + SetSyncVarGameObject(value, ref linkedObject, 1u, ref ___linkedObjectNetId); + } + } + + public string GetContextString(Interactor activator) + { + throw new NotImplementedException(); + } + + public Interactability GetInteractability(Interactor activator) + { + if (!linkedObject) + { + return Interactability.ConditionsNotMet; + } + return Interactability.Available; + } + + public void OnInteractionBegin(Interactor activator) + { + throw new NotImplementedException(); + } + + public bool ShouldIgnoreSpherecastForInteractibility(Interactor activator) + { + return false; + } + + public bool ShouldShowOnScanner() + { + return false; + } + + public bool ShouldProximityHighlight() + { + return false; + } + + private void SetLinkedObject(GameObject newLinkedObject) + { + if (linkedObject != newLinkedObject) + { + NetworklinkedObject = newLinkedObject; + linkedGatewayProjectileController = (linkedObject ? linkedObject.GetComponent() : null); + if ((bool)linkedGatewayProjectileController) + { + linkedGatewayProjectileController.SetLinkedObject(base.gameObject); + } + } + } + + private void Awake() + { + projectileController = GetComponent(); + projectileTargetComponent = GetComponent(); + } + + public override void OnStartServer() + { + base.OnStartServer(); + if ((bool)projectileTargetComponent.target) + { + SetLinkedObject(projectileTargetComponent.target.gameObject); + return; + } + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.position = base.transform.position; + fireProjectileInfo.rotation = base.transform.rotation; + fireProjectileInfo.target = base.gameObject; + fireProjectileInfo.owner = projectileController.owner; + fireProjectileInfo.speedOverride = 0f; + fireProjectileInfo.projectilePrefab = LegacyResourcesAPI.Load("Prefabs/Projectiles/GatewayProjectile"); + ProjectileManager.instance.FireProjectile(fireProjectileInfo); + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(linkedObject); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(linkedObject); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + ___linkedObjectNetId = reader.ReadNetworkId(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + SetLinkedObject(reader.ReadGameObject()); + } + } + + public override void PreStartClient() + { + if (!___linkedObjectNetId.IsEmpty()) + { + NetworklinkedObject = ClientScene.FindLocalObject(___linkedObjectNetId); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/GummyCloneProjectile.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/GummyCloneProjectile.cs new file mode 100644 index 0000000..fa722c7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/GummyCloneProjectile.cs @@ -0,0 +1,103 @@ +using System; +using EntityStates.GummyClone; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class GummyCloneProjectile : MonoBehaviour, IProjectileImpactBehavior +{ + [SerializeField] + private int damageBoostCount = 10; + + [SerializeField] + private int hpBoostCount = 10; + + [SerializeField] + private float maxLifetime = 10f; + + private float stopwatch; + + private bool isAlive = true; + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (isAlive) + { + SpawnGummyClone(); + isAlive = false; + } + } + + protected void FixedUpdate() + { + stopwatch += Time.fixedDeltaTime; + if (NetworkServer.active && (!isAlive || stopwatch > maxLifetime)) + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + public void SpawnGummyClone() + { + ProjectileController component = GetComponent(); + if (!component || !component.owner) + { + return; + } + CharacterBody component2 = component.owner.GetComponent(); + if (!component2) + { + return; + } + CharacterMaster characterMaster = component2.master; + if (!characterMaster || characterMaster.IsDeployableLimited(DeployableSlot.GummyClone)) + { + return; + } + MasterCopySpawnCard masterCopySpawnCard = MasterCopySpawnCard.FromMaster(characterMaster, copyItems: false, copyEquipment: false); + if (!masterCopySpawnCard) + { + return; + } + masterCopySpawnCard.GiveItem(DLC1Content.Items.GummyCloneIdentifier); + masterCopySpawnCard.GiveItem(RoR2Content.Items.BoostDamage, damageBoostCount); + masterCopySpawnCard.GiveItem(RoR2Content.Items.BoostHp, hpBoostCount); + Transform spawnOnTarget = base.transform; + DirectorPlacementRule directorPlacementRule = new DirectorPlacementRule + { + spawnOnTarget = spawnOnTarget, + placementMode = DirectorPlacementRule.PlacementMode.Direct + }; + DirectorCore.GetMonsterSpawnDistance(DirectorCore.MonsterSpawnDistance.Close, out directorPlacementRule.minDistance, out directorPlacementRule.maxDistance); + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(masterCopySpawnCard, directorPlacementRule, new Xoroshiro128Plus(Run.instance.seed + (ulong)Run.instance.fixedTime)); + directorSpawnRequest.teamIndexOverride = characterMaster.teamIndex; + directorSpawnRequest.ignoreTeamMemberLimit = true; + directorSpawnRequest.summonerBodyObject = component2.gameObject; + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult result) + { + CharacterMaster component3 = result.spawnedInstance.GetComponent(); + Deployable deployable = result.spawnedInstance.AddComponent(); + characterMaster.AddDeployable(deployable, DeployableSlot.GummyClone); + deployable.onUndeploy = deployable.onUndeploy ?? new UnityEvent(); + deployable.onUndeploy.AddListener(component3.TrueKill); + GameObject bodyObject = component3.GetBodyObject(); + if ((bool)bodyObject) + { + EntityStateMachine[] components = bodyObject.GetComponents(); + foreach (EntityStateMachine entityStateMachine in components) + { + if (entityStateMachine.customName == "Body") + { + entityStateMachine.SetState(new GummyCloneSpawnState()); + break; + } + } + } + }); + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + UnityEngine.Object.Destroy(masterCopySpawnCard); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/HookProjectileImpact.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/HookProjectileImpact.cs new file mode 100644 index 0000000..9f65ef3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/HookProjectileImpact.cs @@ -0,0 +1,380 @@ +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class HookProjectileImpact : NetworkBehaviour, IProjectileImpactBehavior +{ + private enum HookState + { + Flying, + HitDelay, + Reel, + ReelFail + } + + private ProjectileController projectileController; + + public float reelDelayTime; + + public float reelSpeed = 40f; + + public string attachmentString; + + public float victimPullFactor = 1f; + + public float pullMinimumDistance = 10f; + + public GameObject impactSpark; + + public GameObject impactSuccess; + + [SyncVar] + private HookState hookState; + + [SyncVar] + private GameObject victim; + + private Transform ownerTransform; + + private ProjectileDamage projectileDamage; + + private Rigidbody rigidbody; + + public float liveTimer; + + private float delayTimer; + + private float flyTimer; + + private NetworkInstanceId ___victimNetId; + + public HookState NetworkhookState + { + get + { + return hookState; + } + [param: In] + set + { + ulong newValueAsUlong = (ulong)value; + ulong fieldValueAsUlong = (ulong)hookState; + SetSyncVarEnum(value, newValueAsUlong, ref hookState, fieldValueAsUlong, 1u); + } + } + + public GameObject Networkvictim + { + get + { + return victim; + } + [param: In] + set + { + SetSyncVarGameObject(value, ref victim, 2u, ref ___victimNetId); + } + } + + private void Start() + { + rigidbody = GetComponent(); + projectileController = GetComponent(); + projectileDamage = GetComponent(); + ownerTransform = projectileController.owner.transform; + if (!ownerTransform) + { + return; + } + ModelLocator component = ownerTransform.GetComponent(); + if (!component) + { + return; + } + Transform modelTransform = component.modelTransform; + if ((bool)modelTransform) + { + ChildLocator component2 = modelTransform.GetComponent(); + if ((bool)component2) + { + ownerTransform = component2.FindChild(attachmentString); + } + } + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + EffectManager.SimpleImpactEffect(impactSpark, impactInfo.estimatedPointOfImpact, -base.transform.forward, transmit: true); + if (hookState != 0) + { + return; + } + HurtBox component = impactInfo.collider.GetComponent(); + if ((bool)component) + { + HealthComponent healthComponent = component.healthComponent; + if ((bool)healthComponent) + { + TeamIndex teamIndex = projectileController.teamFilter.teamIndex; + if (!FriendlyFireManager.ShouldDirectHitProceed(healthComponent, teamIndex)) + { + return; + } + Networkvictim = healthComponent.gameObject; + DamageInfo damageInfo = new DamageInfo(); + if ((bool)projectileDamage) + { + damageInfo.damage = projectileDamage.damage; + damageInfo.crit = projectileDamage.crit; + damageInfo.attacker = (projectileController.owner ? projectileController.owner.gameObject : null); + damageInfo.inflictor = base.gameObject; + damageInfo.position = impactInfo.estimatedPointOfImpact; + damageInfo.force = projectileDamage.force * base.transform.forward; + damageInfo.procChainMask = projectileController.procChainMask; + damageInfo.procCoefficient = projectileController.procCoefficient; + damageInfo.damageColorIndex = projectileDamage.damageColorIndex; + } + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject); + NetworkhookState = HookState.HitDelay; + EffectManager.SimpleImpactEffect(impactSuccess, impactInfo.estimatedPointOfImpact, -base.transform.forward, transmit: true); + base.gameObject.layer = LayerIndex.noCollision.intVal; + } + } + if (!victim) + { + NetworkhookState = HookState.ReelFail; + } + } + + private bool Reel() + { + Vector3 vector = ownerTransform.position - victim.transform.position; + Vector3 normalized = vector.normalized; + float num = vector.magnitude; + Collider component = projectileController.owner.GetComponent(); + Collider component2 = victim.GetComponent(); + if ((bool)component && (bool)component2) + { + num = Util.EstimateSurfaceDistance(component, component2); + } + bool flag = num <= pullMinimumDistance; + CharacterMotor characterMotor = null; + Rigidbody rigidbody = null; + float num2 = -1f; + characterMotor = projectileController.owner.GetComponent(); + if ((bool)characterMotor) + { + num2 = characterMotor.mass; + } + else + { + rigidbody = projectileController.owner.GetComponent(); + if ((bool)rigidbody) + { + num2 = rigidbody.mass; + } + } + CharacterMotor characterMotor2 = null; + Rigidbody rigidbody2 = null; + float num3 = -1f; + characterMotor2 = victim.GetComponent(); + if ((bool)characterMotor2) + { + num3 = characterMotor2.mass; + } + else + { + rigidbody2 = victim.GetComponent(); + if ((bool)rigidbody2) + { + num3 = rigidbody2.mass; + } + } + float num4 = 0f; + float num5 = 0f; + if (num2 > 0f && num3 > 0f) + { + num4 = 1f - num2 / (num2 + num3); + num5 = 1f - num4; + } + else if (num2 > 0f) + { + num4 = 1f; + } + else if (num3 > 0f) + { + num5 = 1f; + } + else + { + flag = true; + } + if (flag) + { + num4 = 0f; + num5 = 0f; + } + Vector3 velocity = normalized * (num5 * victimPullFactor * reelSpeed); + if ((bool)characterMotor2) + { + characterMotor2.velocity = velocity; + } + if ((bool)rigidbody2) + { + rigidbody2.velocity = velocity; + } + return flag; + } + + public void FixedUpdate() + { + if (NetworkServer.active && !projectileController.owner) + { + Object.Destroy(base.gameObject); + return; + } + if ((bool)victim) + { + rigidbody.MovePosition(victim.transform.position); + } + switch (hookState) + { + case HookState.Flying: + if (NetworkServer.active) + { + flyTimer += Time.fixedDeltaTime; + if (flyTimer >= liveTimer) + { + NetworkhookState = HookState.ReelFail; + } + } + break; + case HookState.HitDelay: + if (!NetworkServer.active) + { + break; + } + if ((bool)victim) + { + delayTimer += Time.fixedDeltaTime; + if (delayTimer >= reelDelayTime) + { + NetworkhookState = HookState.Reel; + } + } + else + { + NetworkhookState = HookState.Reel; + } + break; + case HookState.Reel: + { + bool flag = true; + if ((bool)victim) + { + flag = Reel(); + } + if (NetworkServer.active) + { + if (!victim) + { + NetworkhookState = HookState.ReelFail; + } + if (flag) + { + Object.Destroy(base.gameObject); + } + } + break; + } + case HookState.ReelFail: + if (!NetworkServer.active) + { + break; + } + if ((bool)rigidbody) + { + rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete; + rigidbody.isKinematic = true; + } + if ((bool)ownerTransform) + { + rigidbody.MovePosition(Vector3.MoveTowards(base.transform.position, ownerTransform.position, reelSpeed * Time.fixedDeltaTime)); + if (base.transform.position == ownerTransform.position) + { + Object.Destroy(base.gameObject); + } + } + break; + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write((int)hookState); + writer.Write(victim); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write((int)hookState); + } + if ((base.syncVarDirtyBits & 2u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(victim); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + hookState = (HookState)reader.ReadInt32(); + ___victimNetId = reader.ReadNetworkId(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + hookState = (HookState)reader.ReadInt32(); + } + if (((uint)num & 2u) != 0) + { + victim = reader.ReadGameObject(); + } + } + + public override void PreStartClient() + { + if (!___victimNetId.IsEmpty()) + { + Networkvictim = ClientScene.FindLocalObject(___victimNetId); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/IProjectileImpactBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/IProjectileImpactBehavior.cs new file mode 100644 index 0000000..110b88b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/IProjectileImpactBehavior.cs @@ -0,0 +1,6 @@ +namespace RoR2.Projectile; + +public interface IProjectileImpactBehavior +{ + void OnProjectileImpact(ProjectileImpactInfo impactInfo); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/LunarSunProjectileController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/LunarSunProjectileController.cs new file mode 100644 index 0000000..2ee96be --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/LunarSunProjectileController.cs @@ -0,0 +1,49 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[DisallowMultipleComponent] +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileImpactExplosion))] +[RequireComponent(typeof(ProjectileOwnerOrbiter))] +public class LunarSunProjectileController : MonoBehaviour +{ + private ProjectileImpactExplosion explosion; + + public void OnEnable() + { + explosion = GetComponent(); + if (NetworkServer.active) + { + ProjectileController component = GetComponent(); + if ((bool)component.owner) + { + AcquireOwner(component); + } + else + { + component.onInitialized += AcquireOwner; + } + } + } + + private void AcquireOwner(ProjectileController controller) + { + controller.onInitialized -= AcquireOwner; + CharacterBody component = controller.owner.GetComponent(); + if ((bool)component) + { + ProjectileOwnerOrbiter component2 = GetComponent(); + component.GetComponent().InitializeOrbiter(component2, this); + } + } + + public void Detonate() + { + if ((bool)explosion) + { + explosion.Detonate(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/MegacrabProjectileController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/MegacrabProjectileController.cs new file mode 100644 index 0000000..281c209 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/MegacrabProjectileController.cs @@ -0,0 +1,156 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +public class MegacrabProjectileController : MonoBehaviour +{ + public enum MegacrabProjectileType + { + White, + Black, + Count + } + + [Header("Cached Properties")] + public ProjectileController projectileController; + + public ProjectileDamage projectileDamage; + + public Rigidbody projectileRigidbody; + + public MegacrabProjectileType megacrabProjectileType; + + [Header("Black Properties")] + public AnimationCurve blackForceFalloffCurve; + + public float whiteToBlackTransformationRadius; + + public GameObject whiteToBlackTransformedProjectile; + + [Header("White Properties")] + public AnimationCurve whiteForceFalloffCurve; + + public float minimumWhiteForceMagnitude; + + public float maximumWhiteForceMagnitude; + + public float whiteMinimumForceToFullyRotate; + + public float whiteScaleSmoothtimeMin = 0.1f; + + public float whiteScaleSmoothtimeMax = 0.1f; + + [Range(0f, 1f)] + public float whitePoisson; + + public static List whiteProjectileList = new List(); + + public static List blackProjectileList = new List(); + + private float whiteScaleSmoothtime; + + private Vector3 whiteScaleVelocity; + + private float whiteRotationVelocity; + + private void OnEnable() + { + switch (megacrabProjectileType) + { + case MegacrabProjectileType.White: + whiteProjectileList.Add(this); + break; + case MegacrabProjectileType.Black: + blackProjectileList.Add(this); + break; + } + } + + private void OnDisable() + { + switch (megacrabProjectileType) + { + case MegacrabProjectileType.White: + whiteProjectileList.Remove(this); + break; + case MegacrabProjectileType.Black: + blackProjectileList.Remove(this); + break; + } + } + + private void Start() + { + whiteScaleSmoothtime = Random.Range(whiteScaleSmoothtimeMin, whiteScaleSmoothtimeMax); + } + + private void FixedUpdate() + { + Vector3 zero = Vector3.zero; + Vector3 position = base.transform.position; + switch (megacrabProjectileType) + { + case MegacrabProjectileType.White: + { + for (int j = 0; j < blackProjectileList.Count; j++) + { + Vector3 vector3 = blackProjectileList[j].transform.position - position; + float magnitude2 = vector3.magnitude; + Vector3 vector4 = whiteForceFalloffCurve.Evaluate(magnitude2) * vector3.normalized; + zero += vector4; + } + Quaternion rotation = base.transform.rotation; + Quaternion target = base.transform.rotation; + Vector3 localScale = base.transform.localScale; + Vector3 target2 = Vector3.one; + if (zero.magnitude > minimumWhiteForceMagnitude) + { + Quaternion b = Quaternion.LookRotation(zero); + float num = Mathf.Min(maximumWhiteForceMagnitude, zero.magnitude); + float num2 = 1f / Mathf.Lerp(num, 1f, whitePoisson); + target2 = new Vector3(num2, num2, num); + target = Quaternion.Slerp(rotation, b, whiteMinimumForceToFullyRotate); + } + base.transform.localScale = Vector3.SmoothDamp(localScale, target2, ref whiteScaleVelocity, whiteScaleSmoothtime); + base.transform.rotation = Util.SmoothDampQuaternion(rotation, target, ref whiteRotationVelocity, whiteScaleSmoothtime); + break; + } + case MegacrabProjectileType.Black: + { + for (int i = 0; i < whiteProjectileList.Count; i++) + { + Vector3 vector = whiteProjectileList[i].transform.position - position; + float magnitude = vector.magnitude; + Vector3 vector2 = blackForceFalloffCurve.Evaluate(magnitude) * vector.normalized; + zero += vector2; + } + projectileRigidbody.AddForce(zero); + break; + } + } + } + + public void OnDestroy() + { + if (!NetworkServer.active || megacrabProjectileType != MegacrabProjectileType.Black) + { + return; + } + Vector3 position = base.transform.position; + for (int i = 0; i < whiteProjectileList.Count; i++) + { + MegacrabProjectileController megacrabProjectileController = whiteProjectileList[i]; + if ((whiteProjectileList[i].transform.position - position).magnitude <= whiteToBlackTransformationRadius) + { + ProjectileExplosion component = megacrabProjectileController.GetComponent(); + if (component.GetAlive()) + { + ProjectileManager.instance.FireProjectile(whiteToBlackTransformedProjectile, megacrabProjectileController.transform.position, Quaternion.identity, projectileController.owner, projectileDamage.damage, 0f, projectileDamage.crit); + component.SetAlive(newAlive: false); + } + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/MineProximityDetonator.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/MineProximityDetonator.cs new file mode 100644 index 0000000..4c3b64b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/MineProximityDetonator.cs @@ -0,0 +1,34 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +public class MineProximityDetonator : MonoBehaviour +{ + public TeamFilter myTeamFilter; + + public UnityEvent triggerEvents; + + public void OnTriggerEnter(Collider collider) + { + if (!NetworkServer.active || !collider) + { + return; + } + HurtBox component = collider.GetComponent(); + if (!component) + { + return; + } + HealthComponent healthComponent = component.healthComponent; + if ((bool)healthComponent) + { + TeamComponent component2 = healthComponent.GetComponent(); + if (!component2 || component2.teamIndex != myTeamFilter.teamIndex) + { + triggerEvents?.Invoke(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/MissileController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/MissileController.cs new file mode 100644 index 0000000..258f8fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/MissileController.cs @@ -0,0 +1,101 @@ +using System.Linq; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(Rigidbody))] +[RequireComponent(typeof(ProjectileTargetComponent))] +public class MissileController : MonoBehaviour +{ + private new Transform transform; + + private Rigidbody rigidbody; + + private TeamFilter teamFilter; + + private ProjectileTargetComponent targetComponent; + + public float maxVelocity; + + public float rollVelocity; + + public float acceleration; + + public float delayTimer; + + public float giveupTimer = 8f; + + public float deathTimer = 10f; + + private float timer; + + private QuaternionPID torquePID; + + public float turbulence; + + public float maxSeekDistance = 40f; + + private BullseyeSearch search = new BullseyeSearch(); + + private void Awake() + { + if (!NetworkServer.active) + { + base.enabled = false; + return; + } + transform = base.transform; + rigidbody = GetComponent(); + torquePID = GetComponent(); + teamFilter = GetComponent(); + targetComponent = GetComponent(); + } + + private void FixedUpdate() + { + timer += Time.deltaTime; + if (timer < giveupTimer) + { + rigidbody.velocity = transform.forward * maxVelocity; + if ((bool)targetComponent.target && timer >= delayTimer) + { + rigidbody.velocity = transform.forward * (maxVelocity + timer * acceleration); + Vector3 vector = targetComponent.target.position + Random.insideUnitSphere * turbulence - transform.position; + if (vector != Vector3.zero) + { + Quaternion rotation = transform.rotation; + Quaternion targetQuat = Util.QuaternionSafeLookRotation(vector); + torquePID.inputQuat = rotation; + torquePID.targetQuat = targetQuat; + rigidbody.angularVelocity = torquePID.UpdatePID(); + } + } + } + if (!targetComponent.target) + { + targetComponent.target = FindTarget(); + } + else + { + HealthComponent component = targetComponent.target.GetComponent(); + if ((bool)component && !component.alive) + { + targetComponent.target = FindTarget(); + } + } + if (timer > deathTimer) + { + Object.Destroy(base.gameObject); + } + } + + private Transform FindTarget() + { + search.searchOrigin = transform.position; + search.searchDirection = transform.forward; + search.teamMaskFilter.RemoveTeam(teamFilter.teamIndex); + search.RefreshCandidates(); + return search.GetResults().FirstOrDefault()?.transform; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileCallOnOwnerNearby.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileCallOnOwnerNearby.cs new file mode 100644 index 0000000..63f90c9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileCallOnOwnerNearby.cs @@ -0,0 +1,91 @@ +using System; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileCallOnOwnerNearby : MonoBehaviour +{ + [Flags] + public enum Filter + { + None = 0, + Server = 1, + Client = 2 + } + + private enum State + { + Outside, + Inside + } + + public Filter filter; + + public float radius; + + public UnityEvent onOwnerEnter; + + public UnityEvent onOwnerExit; + + private State state; + + private bool ownerInRadius; + + private ProjectileController projectileController; + + private void Awake() + { + projectileController = GetComponent(); + Filter filter = Filter.None; + if (NetworkServer.active) + { + filter |= Filter.Server; + } + if (NetworkClient.active) + { + filter |= Filter.Client; + } + if ((this.filter & filter) == 0) + { + base.enabled = false; + } + } + + private void OnDisable() + { + SetState(State.Outside); + } + + private void SetState(State newState) + { + if (state != newState) + { + state = newState; + if (state == State.Inside) + { + onOwnerEnter?.Invoke(); + } + else + { + onOwnerExit?.Invoke(); + } + } + } + + private void FixedUpdate() + { + State state = State.Outside; + if ((bool)projectileController.owner) + { + float num = radius * radius; + if ((base.transform.position - projectileController.owner.transform.position).sqrMagnitude < num) + { + state = State.Inside; + } + } + SetState(state); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileCharacterController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileCharacterController.cs new file mode 100644 index 0000000..d02b374 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileCharacterController.cs @@ -0,0 +1,44 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(CharacterController))] +public class ProjectileCharacterController : MonoBehaviour +{ + private Vector3 downVector; + + public float velocity; + + public float lifetime = 5f; + + private float timer; + + private ProjectileController projectileController; + + private CharacterController characterController; + + private void Awake() + { + downVector = Vector3.down * 3f; + projectileController = GetComponent(); + characterController = GetComponent(); + } + + private void FixedUpdate() + { + if (NetworkServer.active || projectileController.isPrediction) + { + characterController.Move((base.transform.forward + downVector) * (velocity * Time.fixedDeltaTime)); + } + if (NetworkServer.active) + { + timer += Time.fixedDeltaTime; + if (timer > lifetime) + { + Object.Destroy(base.gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileController.cs new file mode 100644 index 0000000..f0dc2a7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileController.cs @@ -0,0 +1,412 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using RoR2.Audio; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(TeamFilter))] +public class ProjectileController : NetworkBehaviour +{ + [HideInInspector] + [Tooltip("This is assigned to the prefab automatically by ProjectileCatalog at runtime. Do not set this value manually.")] + public int catalogIndex = -1; + + [Tooltip("The prefab to instantiate as the visual representation of this projectile. The prefab must have a ProjectileGhostController attached.")] + public GameObject ghostPrefab; + + [Tooltip("The transform for the ghost to follow. If null, the transform of this object will be used instead.")] + public Transform ghostTransformAnchor; + + [Tooltip("The sound to play on Start(). Use this field to ensure the sound only plays once when prediction creates two instances.")] + public string startSound; + + [Tooltip("Prevents this projectile from being deleted by gameplay events, like Captain's defense matrix.")] + public bool cannotBeDeleted; + + [Tooltip("Check this if you want collision events to only run on the local authority (which may be a client instead of the host). 99% of projectiles should have this set to false.")] + public bool authorityHandlesCollisionEvents; + + [SerializeField] + [Tooltip("The sound loop to play while this object exists. Use this field to ensure the sound only plays once when prediction creates two instances.")] + private LoopSoundDef flightSoundLoop; + + protected Rigidbody rigidbody; + + public bool canImpactOnTrigger; + + public bool allowPrediction = true; + + [NonSerialized] + [SyncVar] + public ushort predictionId; + + [SyncVar] + [HideInInspector] + public GameObject owner; + + [HideInInspector] + public bool localCollisionHappened; + + public float procCoefficient = 1f; + + private Collider[] myColliders; + + protected EffectManagerHelper _efhGhost; + + public bool CheckChildrenForCollidersAndIncludeDisabled; + + private NetworkInstanceId ___ownerNetId; + + public TeamFilter teamFilter { get; private set; } + + public ProjectileGhostController ghost { get; set; } + + public bool isPrediction { get; set; } + + public bool shouldPlaySounds { get; set; } + + public ProcChainMask procChainMask { get; set; } + + public NetworkConnection clientAuthorityOwner { get; private set; } + + public ushort NetworkpredictionId + { + get + { + return predictionId; + } + [param: In] + set + { + SetSyncVar(value, ref predictionId, 1u); + } + } + + public GameObject Networkowner + { + get + { + return owner; + } + [param: In] + set + { + SetSyncVarGameObject(value, ref owner, 2u, ref ___ownerNetId); + } + } + + public event Action onInitialized; + + private void Awake() + { + rigidbody = GetComponent(); + teamFilter = GetComponent(); + if (CheckChildrenForCollidersAndIncludeDisabled) + { + myColliders = GetComponentsInChildren(includeInactive: true); + } + else + { + myColliders = GetComponents(); + } + for (int i = 0; i < myColliders.Length; i++) + { + myColliders[i].enabled = false; + } + } + + private void Start() + { + for (int i = 0; i < myColliders.Length; i++) + { + myColliders[i].enabled = true; + } + IgnoreCollisionsWithOwner(shouldIgnore: true); + if (!isPrediction && !NetworkServer.active) + { + ProjectileManager.instance.OnClientProjectileReceived(this); + } + GameObject gameObject = ProjectileGhostReplacementManager.FindProjectileGhostPrefab(this); + shouldPlaySounds = false; + if (isPrediction || !allowPrediction || !base.hasAuthority) + { + shouldPlaySounds = true; + if ((bool)gameObject) + { + Transform transform = base.transform; + if ((bool)ghostTransformAnchor) + { + transform = ghostTransformAnchor; + } + if (!EffectManager.ShouldUsePooledEffect(gameObject)) + { + ghost = UnityEngine.Object.Instantiate(gameObject, transform.position, transform.rotation).GetComponent(); + } + else + { + _efhGhost = EffectManager.GetAndActivatePooledEffect(gameObject, transform.position, transform.rotation); + ghost = _efhGhost.gameObject.GetComponent(); + } + if (isPrediction) + { + ghost.predictionTransform = transform; + } + else + { + ghost.authorityTransform = transform; + } + ghost.enabled = true; + } + } + clientAuthorityOwner = GetComponent().clientAuthorityOwner; + if (shouldPlaySounds) + { + PointSoundManager.EmitSoundLocal((AkEventIdArg)startSound, base.transform.position); + if ((bool)flightSoundLoop) + { + Util.PlaySound(flightSoundLoop.startSoundName, base.gameObject); + } + } + } + + private void OnDestroy() + { + if (NetworkServer.active && ProjectileManager.instance != null) + { + ProjectileManager.instance.OnServerProjectileDestroyed(this); + } + if (shouldPlaySounds && (bool)flightSoundLoop) + { + Util.PlaySound(flightSoundLoop.stopSoundName, base.gameObject); + } + DisconnectFromGhost(); + } + + public void DisconnectFromGhost() + { + if (!ghost || (isPrediction && (bool)ghost.authorityTransform)) + { + return; + } + RunGhostParentProjectileDestroyedMethod(); + if (!EffectManager.UsePools) + { + UnityEngine.Object.Destroy(ghost.gameObject); + } + else + { + if (!isPrediction && _efhGhost == null) + { + _efhGhost = ghost.emh; + } + if (_efhGhost != null && _efhGhost.OwningPool != null) + { + if (!_efhGhost.HasDestroyOnTimer && !_efhGhost.HasAnimateShaderAlphas) + { + _efhGhost.OwningPool.ReturnObject(_efhGhost); + } + } + else + { + if (_efhGhost != null) + { + Debug.LogFormat("efhGhost has no owning pool {0} {1}", _efhGhost.gameObject.name, _efhGhost.gameObject.GetInstanceID()); + } + UnityEngine.Object.Destroy(ghost.gameObject); + } + } + _efhGhost = null; + ghost = null; + } + + public void RunGhostParentProjectileDestroyedMethod() + { + if ((bool)ghost) + { + ghost.OnParentProjectileDestroyed(); + } + } + + private void OnEnable() + { + InstanceTracker.Add(this); + IgnoreCollisionsWithOwner(shouldIgnore: true); + } + + private void OnDisable() + { + InstanceTracker.Remove(this); + } + + public void IgnoreCollisionsWithOwner(bool shouldIgnore) + { + if (!owner) + { + return; + } + ModelLocator component = owner.GetComponent(); + if (!component) + { + return; + } + Transform modelTransform = component.modelTransform; + if (!modelTransform) + { + return; + } + HurtBoxGroup component2 = modelTransform.GetComponent(); + if (!component2) + { + return; + } + HurtBox[] hurtBoxes = component2.hurtBoxes; + for (int i = 0; i < hurtBoxes.Length; i++) + { + List gameObjectComponents = GetComponentsCache.GetGameObjectComponents(hurtBoxes[i].gameObject); + int j = 0; + for (int count = gameObjectComponents.Count; j < count; j++) + { + Collider collider = gameObjectComponents[j]; + for (int k = 0; k < myColliders.Length; k++) + { + Collider collider2 = myColliders[k]; + Physics.IgnoreCollision(collider, collider2, shouldIgnore); + } + } + GetComponentsCache.ReturnBuffer(gameObjectComponents); + } + } + + private static Vector3 EstimateContactPoint(ContactPoint[] contacts, Collider collider) + { + if (contacts.Length == 0) + { + return collider.transform.position; + } + return contacts[0].point; + } + + private static Vector3 EstimateContactNormal(ContactPoint[] contacts) + { + if (contacts.Length == 0) + { + return Vector3.zero; + } + return contacts[0].normal; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool CanProcessCollisionEvents() + { + if ((authorityHandlesCollisionEvents || !NetworkServer.active) && (!authorityHandlesCollisionEvents || !Util.HasEffectiveAuthority(base.gameObject))) + { + return isPrediction; + } + return true; + } + + public void OnCollisionEnter(Collision collision) + { + localCollisionHappened = true; + if (CanProcessCollisionEvents()) + { + ContactPoint[] contacts = collision.contacts; + ProjectileImpactInfo projectileImpactInfo = default(ProjectileImpactInfo); + projectileImpactInfo.collider = collision.collider; + projectileImpactInfo.estimatedPointOfImpact = EstimateContactPoint(contacts, collision.collider); + projectileImpactInfo.estimatedImpactNormal = EstimateContactNormal(contacts); + ProjectileImpactInfo impactInfo = projectileImpactInfo; + IProjectileImpactBehavior[] components = GetComponents(); + for (int i = 0; i < components.Length; i++) + { + components[i].OnProjectileImpact(impactInfo); + } + } + } + + public void DispatchOnInitialized() + { + this.onInitialized?.Invoke(this); + } + + private void OnValidate() + { + if (!Application.IsPlaying(this)) + { + bool flag = GetComponent().localPlayerAuthority; + if (allowPrediction && !flag) + { + Debug.LogWarningFormat(base.gameObject, "ProjectileController: {0} allows predictions, so it should have localPlayerAuthority=true", base.gameObject); + } + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.WritePackedUInt32(predictionId); + writer.Write(owner); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.WritePackedUInt32(predictionId); + } + if ((base.syncVarDirtyBits & 2u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(owner); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + predictionId = (ushort)reader.ReadPackedUInt32(); + ___ownerNetId = reader.ReadNetworkId(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + predictionId = (ushort)reader.ReadPackedUInt32(); + } + if (((uint)num & 2u) != 0) + { + owner = reader.ReadGameObject(); + } + } + + public override void PreStartClient() + { + if (!___ownerNetId.IsEmpty()) + { + Networkowner = ClientScene.FindLocalObject(___ownerNetId); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileControllerTrigger.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileControllerTrigger.cs new file mode 100644 index 0000000..1de0e2e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileControllerTrigger.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(TeamFilter))] +public class ProjectileControllerTrigger : ProjectileController +{ + public void OnTriggerEnter(Collider collider) + { + if (NetworkServer.active && canImpactOnTrigger) + { + Vector3 vector = Vector3.zero; + if ((bool)rigidbody) + { + vector = rigidbody.velocity; + } + ProjectileImpactInfo projectileImpactInfo = default(ProjectileImpactInfo); + projectileImpactInfo.collider = collider; + projectileImpactInfo.estimatedPointOfImpact = base.transform.position; + projectileImpactInfo.estimatedImpactNormal = -vector.normalized; + ProjectileImpactInfo impactInfo = projectileImpactInfo; + IProjectileImpactBehavior[] components = GetComponents(); + for (int i = 0; i < components.Length; i++) + { + components[i].OnProjectileImpact(impactInfo); + } + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool flag = base.OnSerialize(writer, forceAll); + bool flag2 = default(bool); + return flag2 || flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + base.OnDeserialize(reader, initialState); + } + + public override void PreStartClient() + { + base.PreStartClient(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDamage.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDamage.cs new file mode 100644 index 0000000..e9de401 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDamage.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public class ProjectileDamage : MonoBehaviour +{ + [HideInInspector] + public float damage; + + [HideInInspector] + public bool crit; + + [HideInInspector] + public float force; + + [HideInInspector] + public DamageColorIndex damageColorIndex; + + public DamageTypeCombo damageType; + + [Tooltip("If true, we cap the maximum stacks for this attacker")] + public bool useDotMaxStacksFromAttacker; + + [Tooltip("The number of maximum stacks (if we're capping)")] + public uint dotMaxStacksFromAttacker = uint.MaxValue; + + public void SetDamageTypeViaInt(int newDamageType) + { + damageType = new DamageTypeCombo + { + damageType = (DamageType)newDamageType + }; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDamageTrail.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDamageTrail.cs new file mode 100644 index 0000000..988494c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDamageTrail.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(CharacterController))] +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileDamage))] +public class ProjectileDamageTrail : MonoBehaviour +{ + public GameObject trailPrefab; + + public float damageToTrailDpsFactor = 1f; + + public float trailLifetimeAfterExpiration = 1f; + + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private GameObject currentTrailObject; + + private void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + } + + private void FixedUpdate() + { + if (!currentTrailObject) + { + currentTrailObject = Object.Instantiate(trailPrefab, base.transform.position, base.transform.rotation); + DamageTrail component = currentTrailObject.GetComponent(); + component.damagePerSecond = projectileDamage.damage * damageToTrailDpsFactor; + component.owner = projectileController.owner; + } + else + { + currentTrailObject.transform.position = base.transform.position; + } + } + + private void OnDestroy() + { + DiscontinueTrail(); + } + + private void DiscontinueTrail() + { + if ((bool)currentTrailObject) + { + currentTrailObject.AddComponent().duration = trailLifetimeAfterExpiration; + currentTrailObject.GetComponent().active = false; + currentTrailObject = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDeployToOwner.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDeployToOwner.cs new file mode 100644 index 0000000..f78f127 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDeployToOwner.cs @@ -0,0 +1,37 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(Deployable))] +[RequireComponent(typeof(ProjectileController))] +public class ProjectileDeployToOwner : MonoBehaviour +{ + public DeployableSlot deployableSlot; + + private void Start() + { + if (NetworkServer.active) + { + DeployToOwner(); + } + } + + private void DeployToOwner() + { + GameObject owner = GetComponent().owner; + if (!owner) + { + return; + } + CharacterBody component = owner.GetComponent(); + if ((bool)component) + { + CharacterMaster master = component.master; + if ((bool)master) + { + master.AddDeployable(GetComponent(), deployableSlot); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDirectionalTargetFinder.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDirectionalTargetFinder.cs new file mode 100644 index 0000000..1480214 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDirectionalTargetFinder.cs @@ -0,0 +1,157 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; +using UnityEngine.Serialization; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileTargetComponent))] +[RequireComponent(typeof(TeamFilter))] +public class ProjectileDirectionalTargetFinder : MonoBehaviour +{ + [Tooltip("How far ahead the projectile should look to find a target.")] + public float lookRange; + + [Range(0f, 180f)] + [Tooltip("How wide the cone of vision for this projectile is in degrees. Limit is 180.")] + public float lookCone; + + [Tooltip("How long before searching for a target.")] + public float targetSearchInterval = 0.5f; + + [Tooltip("Will not search for new targets once it has one.")] + public bool onlySearchIfNoTarget; + + [Tooltip("Allows the target to be lost if it's outside the acceptable range.")] + public bool allowTargetLoss; + + [Tooltip("If set, targets can only be found when there is a free line of sight.")] + public bool testLoS; + + [Tooltip("Whether or not airborne characters should be ignored.")] + public bool ignoreAir; + + [Tooltip("The difference in altitude at which a result will be ignored.")] + [FormerlySerializedAs("altitudeTolerance")] + public float flierAltitudeTolerance = float.PositiveInfinity; + + public UnityEvent onNewTargetFound; + + [FormerlySerializedAs("ontargetLost")] + public UnityEvent onTargetLost; + + private new Transform transform; + + private TeamFilter teamFilter; + + private ProjectileTargetComponent targetComponent; + + private float searchTimer; + + private bool hasTarget; + + private bool hadTargetLastUpdate; + + private BullseyeSearch bullseyeSearch; + + private HurtBox lastFoundHurtBox; + + private Transform lastFoundTransform; + + private void Start() + { + if (!NetworkServer.active) + { + base.enabled = false; + return; + } + bullseyeSearch = new BullseyeSearch(); + teamFilter = GetComponent(); + targetComponent = GetComponent(); + transform = base.transform; + searchTimer = 0f; + } + + private void FixedUpdate() + { + searchTimer -= Time.fixedDeltaTime; + if (!(searchTimer <= 0f)) + { + return; + } + searchTimer += targetSearchInterval; + if (allowTargetLoss && (object)targetComponent.target != null && (object)lastFoundTransform == targetComponent.target && !PassesFilters(lastFoundHurtBox)) + { + SetTarget(null); + } + if (!onlySearchIfNoTarget || targetComponent.target == null) + { + SearchForTarget(); + } + hasTarget = targetComponent.target != null; + if (hadTargetLastUpdate != hasTarget) + { + if (hasTarget) + { + onNewTargetFound?.Invoke(); + } + else + { + onTargetLost?.Invoke(); + } + } + hadTargetLastUpdate = hasTarget; + } + + private bool PassesFilters(HurtBox result) + { + CharacterBody body = result.healthComponent.body; + if (!body || (ignoreAir && body.isFlying)) + { + return false; + } + if (body.isFlying && !float.IsInfinity(flierAltitudeTolerance) && flierAltitudeTolerance < Mathf.Abs(result.transform.position.y - transform.position.y)) + { + return false; + } + return true; + } + + private void SearchForTarget() + { + bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral; + bullseyeSearch.teamMaskFilter.RemoveTeam(teamFilter.teamIndex); + bullseyeSearch.filterByLoS = testLoS; + bullseyeSearch.searchOrigin = transform.position; + bullseyeSearch.searchDirection = transform.forward; + bullseyeSearch.maxDistanceFilter = lookRange; + bullseyeSearch.sortMode = BullseyeSearch.SortMode.DistanceAndAngle; + bullseyeSearch.maxAngleFilter = lookCone; + bullseyeSearch.RefreshCandidates(); + IEnumerable source = bullseyeSearch.GetResults().Where(PassesFilters); + SetTarget(source.FirstOrDefault()); + } + + private void SetTarget(HurtBox hurtBox) + { + lastFoundHurtBox = hurtBox; + lastFoundTransform = hurtBox?.transform; + targetComponent.target = lastFoundTransform; + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.yellow; + Transform transform = base.transform; + Vector3 position = transform.position; + Gizmos.DrawWireSphere(position, lookRange); + Gizmos.DrawRay(position, transform.forward * lookRange); + Gizmos.DrawFrustum(position, lookCone * 2f, lookRange, 0f, 1f); + if (!float.IsInfinity(flierAltitudeTolerance)) + { + Gizmos.DrawWireCube(position, new Vector3(lookRange * 2f, flierAltitudeTolerance * 2f, lookRange * 2f)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDotZone.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDotZone.cs new file mode 100644 index 0000000..993d1cf --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileDotZone.cs @@ -0,0 +1,114 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(HitBoxGroup))] +public class ProjectileDotZone : MonoBehaviour, IProjectileImpactBehavior +{ + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + public float damageCoefficient; + + public AttackerFiltering attackerFiltering = AttackerFiltering.NeverHitSelf; + + public GameObject impactEffect; + + public Vector3 forceVector; + + public float overlapProcCoefficient = 1f; + + [Tooltip("The frequency (1/time) at which the overlap attack is tested. Higher values are more accurate but more expensive.")] + public float fireFrequency = 1f; + + [Tooltip("The frequency (1/time) at which the overlap attack is reset. Higher values means more frequent ticks of damage.")] + public float resetFrequency = 20f; + + public float lifetime = 30f; + + [Tooltip("The event that runs at the start.")] + public UnityEvent onBegin; + + [Tooltip("The event that runs at the start.")] + public UnityEvent onEnd; + + private OverlapAttack attack; + + private float fireStopwatch; + + private float resetStopwatch; + + private float totalStopwatch; + + public string soundLoopString = ""; + + public string soundLoopStopString = ""; + + private void Start() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + ResetOverlap(); + onBegin.Invoke(); + if (!string.IsNullOrEmpty(soundLoopString)) + { + Util.PlaySound(soundLoopString, base.gameObject); + } + } + + private void ResetOverlap() + { + attack = new OverlapAttack(); + attack.procChainMask = projectileController.procChainMask; + attack.procCoefficient = projectileController.procCoefficient * overlapProcCoefficient; + attack.attacker = projectileController.owner; + attack.inflictor = base.gameObject; + attack.teamIndex = projectileController.teamFilter.teamIndex; + attack.attackerFiltering = attackerFiltering; + attack.damage = damageCoefficient * projectileDamage.damage; + attack.forceVector = forceVector + projectileDamage.force * base.transform.forward; + attack.hitEffectPrefab = impactEffect; + attack.isCrit = projectileDamage.crit; + attack.damageColorIndex = projectileDamage.damageColorIndex; + attack.damageType = projectileDamage.damageType; + attack.hitBoxGroup = GetComponent(); + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + } + + public void FixedUpdate() + { + if (!NetworkServer.active) + { + return; + } + totalStopwatch += Time.fixedDeltaTime; + resetStopwatch += Time.fixedDeltaTime; + fireStopwatch += Time.fixedDeltaTime; + if (resetStopwatch >= 1f / resetFrequency) + { + ResetOverlap(); + resetStopwatch -= 1f / resetFrequency; + } + if (fireStopwatch >= 1f / fireFrequency) + { + attack.Fire(); + fireStopwatch -= 1f / fireFrequency; + } + if (lifetime > 0f && totalStopwatch >= lifetime) + { + onEnd.Invoke(); + if (!string.IsNullOrEmpty(soundLoopStopString)) + { + Util.PlaySound(soundLoopStopString, base.gameObject); + } + Object.Destroy(base.gameObject); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileExplosion.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileExplosion.cs new file mode 100644 index 0000000..1647752 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileExplosion.cs @@ -0,0 +1,261 @@ +using System; +using HG; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileExplosion : MonoBehaviour +{ + protected ProjectileController projectileController; + + protected ProjectileDamage projectileDamage; + + protected bool alive = true; + + [Header("Main Properties")] + public BlastAttack.FalloffModel falloffModel = BlastAttack.FalloffModel.Linear; + + public float blastRadius; + + [Tooltip("The percentage of the damage, proc coefficient, and force of the initial projectile. Ranges from 0-1")] + public float blastDamageCoefficient; + + public float blastProcCoefficient = 1f; + + public AttackerFiltering blastAttackerFiltering; + + public Vector3 bonusBlastForce; + + public bool canRejectForce = true; + + public HealthComponent projectileHealthComponent; + + public GameObject explosionEffect; + + [Obsolete("This sound will not play over the network. Provide the sound via the prefab referenced by explosionEffect instead.", false)] + [ShowFieldObsolete] + [Tooltip("This sound will not play over the network. Provide the sound via the prefab referenced by explosionEffect instead.")] + public string explosionSoundString; + + [Header("Child Properties")] + [Tooltip("Does this projectile release children on death?")] + public bool fireChildren; + + public GameObject childrenProjectilePrefab; + + public int childrenCount; + + [Tooltip("What percentage of our damage does the children get?")] + public float childrenDamageCoefficient; + + [ShowFieldObsolete] + [Tooltip("How to randomize the orientation of children")] + public Vector3 minAngleOffset; + + [ShowFieldObsolete] + public Vector3 maxAngleOffset; + + public float minRollDegrees; + + public float rangeRollDegrees; + + public float minPitchDegrees; + + public float rangePitchDegrees; + + [Tooltip("useLocalSpaceForChildren is unused by ProjectileImpactExplosion")] + public bool useLocalSpaceForChildren; + + [Tooltip("If true, applies a DoT given the following properties")] + [Header("DoT Properties")] + public bool applyDot; + + public DotController.DotIndex dotIndex = DotController.DotIndex.None; + + [Tooltip("Duration in seconds of the DoT. Unused if calculateTotalDamage is true.")] + public float dotDuration; + + [Tooltip("Multiplier on the per-tick damage")] + public float dotDamageMultiplier = 1f; + + [Tooltip("If true, we cap the numer of DoT stacks for this attacker.")] + public bool applyMaxStacksFromAttacker; + + [Tooltip("The maximum number of stacks that we can apply for this attacker")] + public uint maxStacksFromAttacker = uint.MaxValue; + + [Tooltip("If true, we disregard the duration and instead specify the total damage.")] + public bool calculateTotalDamage; + + [Tooltip("totalDamage = totalDamageMultiplier * attacker's damage")] + public float totalDamageMultiplier; + + protected virtual void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + } + + public void Detonate() + { + if (NetworkServer.active) + { + DetonateServer(); + } + UnityEngine.Object.Destroy(base.gameObject); + } + + protected void DetonateServer() + { + if ((bool)explosionEffect) + { + EffectManager.SpawnEffect(explosionEffect, new EffectData + { + origin = base.transform.position, + scale = blastRadius + }, transmit: true); + } + if ((bool)projectileDamage) + { + BlastAttack blastAttack = new BlastAttack(); + blastAttack.position = base.transform.position; + blastAttack.baseDamage = projectileDamage.damage * blastDamageCoefficient; + blastAttack.baseForce = projectileDamage.force * blastDamageCoefficient; + blastAttack.radius = blastRadius; + blastAttack.attacker = (projectileController.owner ? projectileController.owner.gameObject : null); + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = projectileController.teamFilter.teamIndex; + blastAttack.crit = projectileDamage.crit; + blastAttack.procChainMask = projectileController.procChainMask; + blastAttack.procCoefficient = projectileController.procCoefficient * blastProcCoefficient; + blastAttack.bonusForce = bonusBlastForce; + blastAttack.falloffModel = falloffModel; + blastAttack.damageColorIndex = projectileDamage.damageColorIndex; + blastAttack.damageType = projectileDamage.damageType; + blastAttack.attackerFiltering = blastAttackerFiltering; + blastAttack.canRejectForce = canRejectForce; + BlastAttack.Result result = blastAttack.Fire(); + OnBlastAttackResult(blastAttack, result); + } + if (explosionSoundString.Length > 0) + { + Util.PlaySound(explosionSoundString, base.gameObject); + } + if (fireChildren) + { + for (int i = 0; i < childrenCount; i++) + { + FireChild(); + } + } + } + + protected Quaternion GetRandomChildRollPitch() + { + Quaternion quaternion = Quaternion.AngleAxis(minRollDegrees + UnityEngine.Random.Range(0f, rangeRollDegrees), Vector3.forward); + Quaternion quaternion2 = Quaternion.AngleAxis(minPitchDegrees + UnityEngine.Random.Range(0f, rangePitchDegrees), Vector3.left); + return quaternion * quaternion2; + } + + protected virtual Quaternion GetRandomDirectionForChild() + { + Quaternion randomChildRollPitch = GetRandomChildRollPitch(); + if (useLocalSpaceForChildren) + { + return base.transform.rotation * randomChildRollPitch; + } + return randomChildRollPitch; + } + + protected void FireChild() + { + Quaternion randomDirectionForChild = GetRandomDirectionForChild(); + GameObject obj = UnityEngine.Object.Instantiate(childrenProjectilePrefab, base.transform.position, randomDirectionForChild); + ProjectileController component = obj.GetComponent(); + if ((bool)component) + { + component.procChainMask = projectileController.procChainMask; + component.procCoefficient = projectileController.procCoefficient; + component.Networkowner = projectileController.owner; + } + obj.GetComponent().teamIndex = GetComponent().teamIndex; + ProjectileDamage component2 = obj.GetComponent(); + if ((bool)component2) + { + component2.damage = projectileDamage.damage * childrenDamageCoefficient; + component2.crit = projectileDamage.crit; + component2.force = projectileDamage.force; + component2.damageColorIndex = projectileDamage.damageColorIndex; + } + NetworkServer.Spawn(obj); + } + + public void SetExplosionRadius(float newRadius) + { + blastRadius = newRadius; + } + + public void SetAlive(bool newAlive) + { + alive = newAlive; + } + + public bool GetAlive() + { + if (!NetworkServer.active) + { + return false; + } + return alive; + } + + protected virtual void OnValidate() + { + if (!Application.IsPlaying(this) && !string.IsNullOrEmpty(explosionSoundString)) + { + Debug.LogWarningFormat(base.gameObject, "{0} ProjectileImpactExplosion component supplies a value in the explosionSoundString field. This will not play correctly over the network. Please move the sound to the explosion effect.", Util.GetGameObjectHierarchyName(base.gameObject)); + } + } + + protected virtual void OnBlastAttackResult(BlastAttack blastAttack, BlastAttack.Result result) + { + if (!applyDot) + { + return; + } + CharacterBody characterBody = blastAttack.attacker?.GetComponent(); + BlastAttack.HitPoint[] hitPoints = result.hitPoints; + for (int i = 0; i < hitPoints.Length; i++) + { + BlastAttack.HitPoint hitPoint = hitPoints[i]; + if ((bool)hitPoint.hurtBox && (bool)hitPoint.hurtBox.healthComponent) + { + InflictDotInfo inflictDotInfo = default(InflictDotInfo); + inflictDotInfo.victimObject = hitPoint.hurtBox.healthComponent.gameObject; + inflictDotInfo.attackerObject = blastAttack.attacker; + inflictDotInfo.dotIndex = dotIndex; + inflictDotInfo.damageMultiplier = dotDamageMultiplier; + InflictDotInfo dotInfo = inflictDotInfo; + if (calculateTotalDamage && (bool)characterBody) + { + dotInfo.totalDamage = characterBody.damage * totalDamageMultiplier; + } + else + { + dotInfo.duration = dotDuration; + } + if (applyMaxStacksFromAttacker) + { + dotInfo.maxStacksFromAttacker = maxStacksFromAttacker; + } + if ((bool)characterBody && (bool)characterBody.inventory) + { + StrengthenBurnUtils.CheckDotForUpgrade(characterBody.inventory, ref dotInfo); + } + DotController.InflictDot(ref dotInfo); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFireChildren.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFireChildren.cs new file mode 100644 index 0000000..b859804 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFireChildren.cs @@ -0,0 +1,65 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +public class ProjectileFireChildren : MonoBehaviour +{ + public float duration = 5f; + + public int count = 5; + + public GameObject childProjectilePrefab; + + private float timer; + + private float nextSpawnTimer; + + public float childDamageCoefficient = 1f; + + public float childProcCoefficient = 1f; + + private ProjectileDamage projectileDamage; + + private ProjectileController projectileController; + + public bool ignoreParentForChainController; + + private void Start() + { + projectileDamage = GetComponent(); + projectileController = GetComponent(); + } + + private void Update() + { + timer += Time.deltaTime; + nextSpawnTimer += Time.deltaTime; + if (timer >= duration) + { + Object.Destroy(base.gameObject); + } + if (nextSpawnTimer >= duration / (float)count) + { + nextSpawnTimer -= duration / (float)count; + GameObject obj = Object.Instantiate(childProjectilePrefab, base.transform.position, Util.QuaternionSafeLookRotation(base.transform.forward)); + ProjectileController component = obj.GetComponent(); + if ((bool)component) + { + component.procChainMask = projectileController.procChainMask; + component.procCoefficient = projectileController.procCoefficient * childProcCoefficient; + component.Networkowner = projectileController.owner; + } + obj.GetComponent().teamIndex = GetComponent().teamIndex; + ProjectileDamage component2 = obj.GetComponent(); + if ((bool)component2) + { + component2.damage = projectileDamage.damage * childDamageCoefficient; + component2.crit = projectileDamage.crit; + component2.force = projectileDamage.force; + component2.damageColorIndex = projectileDamage.damageColorIndex; + } + NetworkServer.Spawn(obj); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFireEffects.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFireEffects.cs new file mode 100644 index 0000000..fc9806b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFireEffects.cs @@ -0,0 +1,37 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public class ProjectileFireEffects : MonoBehaviour +{ + public float duration = 5f; + + public int count = 5; + + public GameObject effectPrefab; + + public Vector3 randomOffset; + + private float timer; + + private float nextSpawnTimer; + + private void Update() + { + timer += Time.deltaTime; + nextSpawnTimer += Time.deltaTime; + if (timer >= duration) + { + Object.Destroy(base.gameObject); + } + if (nextSpawnTimer >= duration / (float)count) + { + nextSpawnTimer -= duration / (float)count; + if ((bool)effectPrefab) + { + Vector3 vector = new Vector3(Random.Range(0f - randomOffset.x, randomOffset.x), Random.Range(0f - randomOffset.y, randomOffset.y), Random.Range(0f - randomOffset.z, randomOffset.z)); + EffectManager.SimpleImpactEffect(effectPrefab, base.transform.position + vector, Vector3.forward, transmit: true); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFunballBehavior.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFunballBehavior.cs new file mode 100644 index 0000000..1a1a57e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFunballBehavior.cs @@ -0,0 +1,139 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[Obsolete("This component is deprecated and will likely be removed from future releases.", false)] +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(TeamFilter))] +public class ProjectileFunballBehavior : NetworkBehaviour +{ + [Tooltip("The effect to use for the explosion.")] + public GameObject explosionPrefab; + + [Tooltip("How many seconds until detonation.")] + public float duration; + + [Tooltip("Radius of blast in meters.")] + public float blastRadius = 1f; + + [Tooltip("Maximum damage of blast.")] + public float blastDamage = 1f; + + [Tooltip("Force of blast.")] + public float blastForce = 1f; + + private ProjectileController projectileController; + + [SyncVar] + private float timer; + + private bool fuseStarted; + + public float Networktimer + { + get + { + return timer; + } + [param: In] + set + { + SetSyncVar(value, ref timer, 1u); + } + } + + private void Awake() + { + projectileController = GetComponent(); + } + + private void Start() + { + Networktimer = -1f; + } + + private void FixedUpdate() + { + if (NetworkServer.active && fuseStarted) + { + Networktimer = timer + Time.fixedDeltaTime; + if (timer >= duration) + { + EffectManager.SpawnEffect(explosionPrefab, new EffectData + { + origin = base.transform.position, + scale = blastRadius + }, transmit: true); + BlastAttack blastAttack = new BlastAttack(); + blastAttack.attacker = projectileController.owner; + blastAttack.inflictor = base.gameObject; + blastAttack.teamIndex = projectileController.teamFilter.teamIndex; + blastAttack.position = base.transform.position; + blastAttack.procChainMask = projectileController.procChainMask; + blastAttack.procCoefficient = projectileController.procCoefficient; + blastAttack.radius = blastRadius; + blastAttack.baseDamage = blastDamage; + blastAttack.baseForce = blastForce; + blastAttack.bonusForce = Vector3.zero; + blastAttack.crit = false; + blastAttack.damageType = DamageType.Generic; + blastAttack.Fire(); + UnityEngine.Object.Destroy(base.gameObject); + } + } + } + + private void OnCollisionEnter(Collision collision) + { + fuseStarted = true; + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(timer); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(timer); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + timer = reader.ReadSingle(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + timer = reader.ReadSingle(); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFuse.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFuse.cs new file mode 100644 index 0000000..2ae1596 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileFuse.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileFuse : MonoBehaviour +{ + public float fuse; + + public UnityEvent onFuse; + + private void Awake() + { + if (!NetworkServer.active) + { + base.enabled = false; + } + } + + private void FixedUpdate() + { + fuse -= Time.fixedDeltaTime; + if (fuse <= 0f) + { + base.enabled = false; + onFuse.Invoke(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGhostCluster.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGhostCluster.cs new file mode 100644 index 0000000..926738b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGhostCluster.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public class ProjectileGhostCluster : MonoBehaviour +{ + public GameObject ghostClusterPrefab; + + public int clusterCount; + + public bool distributeEvenly; + + public float clusterDistance; + + private void Start() + { + float num = 1f / (Mathf.Log(clusterCount, 4f) + 1f); + Vector3 position = base.transform.position; + for (int i = 0; i < clusterCount; i++) + { + GameObject obj = Object.Instantiate(position: position + ((!distributeEvenly) ? (Random.insideUnitSphere * clusterDistance) : Vector3.zero), original: ghostClusterPrefab, rotation: Quaternion.identity, parent: base.transform); + obj.transform.localScale = Vector3.one / (Mathf.Log(clusterCount, 4f) + 1f); + TrailRenderer component = obj.GetComponent(); + if ((bool)component) + { + component.widthMultiplier *= num; + } + } + } + + private void Update() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGhostController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGhostController.cs new file mode 100644 index 0000000..4df2f74 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGhostController.cs @@ -0,0 +1,100 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.Projectile; + +public class ProjectileGhostController : MonoBehaviour +{ + private new Transform transform; + + [HideInInspector] + public EffectManagerHelper emh; + + private float migration = 1f; + + [Tooltip("Sets the ghost's scale to match the base projectile.")] + public bool inheritScaleFromProjectile; + + [Tooltip("When my local projectile 'parent' is destroyed, run these.")] + public UnityEvent ParentProjectileDestroyedEvent; + + private bool alreadyRunParentProjectileDestroyedEvent; + + public Transform authorityTransform { get; set; } + + public Transform predictionTransform { get; set; } + + private void Awake() + { + transform = base.transform; + } + + private void Start() + { + if (TryGetComponent(out var component)) + { + emh = component; + } + } + + private void OnEnable() + { + alreadyRunParentProjectileDestroyedEvent = false; + } + + private void FixedUpdate() + { + if ((bool)authorityTransform ^ (bool)predictionTransform) + { + CopyTransform(authorityTransform ? authorityTransform : predictionTransform); + } + else if ((bool)authorityTransform) + { + LerpTransform(predictionTransform, authorityTransform, migration); + if (migration == 1f) + { + predictionTransform = null; + } + } + else if ((bool)emh && emh.OwningPool != null) + { + if (!emh.DontAllowProjectilesToPrematurelyPool) + { + emh.OwningPool.ReturnObject(emh); + } + } + else + { + Object.Destroy(base.gameObject); + } + } + + private void LerpTransform(Transform a, Transform b, float t) + { + transform.position = Vector3.LerpUnclamped(a.position, b.position, t); + transform.rotation = Quaternion.SlerpUnclamped(a.rotation, b.rotation, t); + if (inheritScaleFromProjectile) + { + transform.localScale = Vector3.Lerp(a.localScale, b.localScale, t); + } + } + + private void CopyTransform(Transform src) + { + transform.position = src.position; + transform.rotation = src.rotation; + if (inheritScaleFromProjectile) + { + transform.localScale = src.localScale; + } + } + + public void OnParentProjectileDestroyed() + { + if (!alreadyRunParentProjectileDestroyedEvent) + { + ParentProjectileDestroyedEvent.Invoke(); + alreadyRunParentProjectileDestroyedEvent = true; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGrantOnKillOnDestroy.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGrantOnKillOnDestroy.cs new file mode 100644 index 0000000..4d194c0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGrantOnKillOnDestroy.cs @@ -0,0 +1,39 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(HealthComponent))] +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileDamage))] +public class ProjectileGrantOnKillOnDestroy : MonoBehaviour +{ + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private HealthComponent healthComponent; + + private void OnDestroy() + { + healthComponent = GetComponent(); + projectileController = GetComponent(); + projectileDamage = GetComponent(); + if (NetworkServer.active && (bool)projectileController.owner) + { + DamageInfo damageInfo = new DamageInfo + { + attacker = projectileController.owner, + crit = projectileDamage.crit, + damage = projectileDamage.damage, + position = base.transform.position, + procCoefficient = projectileController.procCoefficient, + damageType = projectileDamage.damageType, + damageColorIndex = projectileDamage.damageColorIndex + }; + HealthComponent victim = healthComponent; + DamageReport damageReport = new DamageReport(damageInfo, victim, damageInfo.damage, healthComponent.combinedHealth); + GlobalEventManager.instance.OnCharacterDeath(damageReport); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGrappleController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGrappleController.cs new file mode 100644 index 0000000..5336d50 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileGrappleController.cs @@ -0,0 +1,488 @@ +using System; +using EntityStates; +using EntityStates.Loader; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileSimple))] +[RequireComponent(typeof(EntityStateMachine))] +[RequireComponent(typeof(ProjectileStickOnImpact))] +public class ProjectileGrappleController : MonoBehaviour +{ + private struct OwnerInfo + { + public readonly GameObject gameObject; + + public readonly CharacterBody characterBody; + + public readonly CharacterMotor characterMotor; + + public readonly Rigidbody rigidbody; + + public readonly EntityStateMachine stateMachine; + + public readonly bool hasEffectiveAuthority; + + public OwnerInfo(GameObject ownerGameObject) + { + this = default(OwnerInfo); + gameObject = ownerGameObject; + if (!gameObject) + { + return; + } + characterBody = gameObject.GetComponent(); + characterMotor = gameObject.GetComponent(); + rigidbody = gameObject.GetComponent(); + hasEffectiveAuthority = Util.HasEffectiveAuthority(gameObject); + EntityStateMachine[] components = gameObject.GetComponents(); + for (int i = 0; i < components.Length; i++) + { + if (components[i].customName == "Hook") + { + stateMachine = components[i]; + break; + } + } + } + } + + private class BaseState : EntityStates.BaseState + { + protected ProjectileGrappleController grappleController; + + protected Vector3 aimOrigin; + + protected Vector3 position; + + protected bool ownerValid { get; private set; } + + protected ref OwnerInfo owner => ref grappleController.owner; + + private void UpdatePositions() + { + aimOrigin = grappleController.owner.characterBody.aimOrigin; + position = base.transform.position + base.transform.up * grappleController.normalOffset; + } + + public override void OnEnter() + { + base.OnEnter(); + grappleController = GetComponent(); + ownerValid = (bool)grappleController && (bool)grappleController.owner.gameObject; + if (ownerValid) + { + UpdatePositions(); + } + } + + public override void FixedUpdate() + { + base.FixedUpdate(); + if (ownerValid) + { + ownerValid &= grappleController.owner.gameObject; + if (ownerValid) + { + UpdatePositions(); + FixedUpdateBehavior(); + } + } + if (NetworkServer.active && !ownerValid) + { + ownerValid = false; + EntityState.Destroy(base.gameObject); + } + } + + protected virtual void FixedUpdateBehavior() + { + if (base.isAuthority && !grappleController.OwnerIsInFiringState()) + { + outer.SetNextState(new ReturnState()); + } + } + + protected Ray GetOwnerAimRay() + { + if (!owner.characterBody) + { + return default(Ray); + } + return owner.characterBody.inputBank.GetAimRay(); + } + } + + private class FlyState : BaseState + { + private float duration; + + public override void OnEnter() + { + base.OnEnter(); + duration = grappleController.maxTravelDistance / grappleController.GetComponent().velocity; + } + + protected override void FixedUpdateBehavior() + { + base.FixedUpdateBehavior(); + if (!base.isAuthority) + { + return; + } + if (grappleController.projectileStickOnImpactController.stuck) + { + EntityState entityState = null; + if ((bool)grappleController.projectileStickOnImpactController.stuckBody) + { + Rigidbody component = grappleController.projectileStickOnImpactController.stuckBody.GetComponent(); + if ((bool)component && component.mass < grappleController.yankMassLimit) + { + CharacterBody component2 = component.GetComponent(); + if (!component2 || !component2.isPlayerControlled || component2.teamComponent.teamIndex != base.projectileController.teamFilter.teamIndex || FriendlyFireManager.ShouldDirectHitProceed(component2.healthComponent, base.projectileController.teamFilter.teamIndex)) + { + entityState = new YankState(); + } + } + } + if (entityState == null) + { + entityState = new GripState(); + } + DeductOwnerStock(); + outer.SetNextState(entityState); + } + else if (duration <= base.fixedAge) + { + outer.SetNextState(new ReturnState()); + } + } + + private void DeductOwnerStock() + { + if (!base.ownerValid || !base.owner.hasEffectiveAuthority) + { + return; + } + SkillLocator component = base.owner.gameObject.GetComponent(); + if ((bool)component) + { + GenericSkill secondary = component.secondary; + if ((bool)secondary) + { + secondary.DeductStock(1); + } + } + } + } + + private class BaseGripState : BaseState + { + protected float currentDistance; + + public override void OnEnter() + { + base.OnEnter(); + currentDistance = Vector3.Distance(aimOrigin, position); + } + + protected override void FixedUpdateBehavior() + { + base.FixedUpdateBehavior(); + currentDistance = Vector3.Distance(aimOrigin, position); + if (base.isAuthority) + { + bool flag = !grappleController.projectileStickOnImpactController.stuck; + bool flag2 = currentDistance < grappleController.nearBreakDistance; + bool flag3 = !grappleController.OwnerIsInFiringState(); + if (!base.owner.stateMachine || !((base.owner.stateMachine.state as BaseSkillState)?.IsKeyDownAuthority() ?? false) || flag3 || flag2 || flag) + { + outer.SetNextState(new ReturnState()); + } + } + } + } + + private class GripState : BaseGripState + { + private float lastDistance; + + private void DeductStockIfStruckNonPylon() + { + GameObject victim = grappleController.projectileStickOnImpactController.victim; + if ((bool)victim) + { + GameObject gameObject = victim; + EntityLocator component = gameObject.GetComponent(); + if ((bool)component) + { + gameObject = component.entity; + } + _ = (bool)gameObject.GetComponent(); + } + } + + public override void OnEnter() + { + base.OnEnter(); + lastDistance = Vector3.Distance(aimOrigin, position); + if (base.ownerValid) + { + grappleController.didStick = true; + if ((bool)base.owner.characterMotor) + { + Vector3 direction = GetOwnerAimRay().direction; + Vector3 velocity = base.owner.characterMotor.velocity; + velocity = ((Vector3.Dot(velocity, direction) < 0f) ? Vector3.zero : Vector3.Project(velocity, direction)); + velocity += direction * grappleController.initialLookImpulse; + velocity += base.owner.characterMotor.moveDirection * grappleController.initiallMoveImpulse; + base.owner.characterMotor.velocity = velocity; + } + } + } + + protected override void FixedUpdateBehavior() + { + base.FixedUpdateBehavior(); + float num = grappleController.acceleration; + if (currentDistance > lastDistance) + { + num *= grappleController.escapeForceMultiplier; + } + lastDistance = currentDistance; + if (base.owner.hasEffectiveAuthority && (bool)base.owner.characterMotor && (bool)base.owner.characterBody) + { + Ray ownerAimRay = GetOwnerAimRay(); + Vector3 normalized = (base.transform.position - base.owner.characterBody.aimOrigin).normalized; + Vector3 vector = normalized * num; + float time = Mathf.Clamp01(base.fixedAge / grappleController.lookAccelerationRampUpDuration); + float num2 = grappleController.lookAccelerationRampUpCurve.Evaluate(time); + float num3 = Util.Remap(Vector3.Dot(ownerAimRay.direction, normalized), -1f, 1f, 1f, 0f); + vector += ownerAimRay.direction * (grappleController.lookAcceleration * num2 * num3); + vector += base.owner.characterMotor.moveDirection * grappleController.moveAcceleration; + base.owner.characterMotor.ApplyForce(vector * (base.owner.characterMotor.mass * Time.fixedDeltaTime), alwaysApply: true, disableAirControlUntilCollision: true); + } + } + } + + private class YankState : BaseGripState + { + public static float yankSpeed; + + public static float delayBeforeYanking; + + public static float hoverTimeLimit = 0.5f; + + private CharacterBody stuckBody; + + public override void OnEnter() + { + base.OnEnter(); + stuckBody = grappleController.projectileStickOnImpactController.stuckBody; + } + + protected override void FixedUpdateBehavior() + { + base.FixedUpdateBehavior(); + if (!stuckBody) + { + return; + } + if (Util.HasEffectiveAuthority(stuckBody.gameObject)) + { + Vector3 vector = aimOrigin - position; + IDisplacementReceiver component = stuckBody.GetComponent(); + if ((bool)(Component)component && base.fixedAge >= delayBeforeYanking) + { + component.AddDisplacement(vector * (yankSpeed * Time.fixedDeltaTime)); + } + } + if (base.owner.hasEffectiveAuthority && (bool)base.owner.characterMotor && base.fixedAge < hoverTimeLimit) + { + Vector3 velocity = base.owner.characterMotor.velocity; + if (velocity.y < 0f) + { + velocity.y = 0f; + base.owner.characterMotor.velocity = velocity; + } + } + } + } + + private class ReturnState : BaseState + { + private float returnSpeedAcceleration = 240f; + + private float returnSpeed; + + public override void OnEnter() + { + base.OnEnter(); + if (base.ownerValid) + { + returnSpeed = grappleController.projectileSimple.velocity; + returnSpeedAcceleration = returnSpeed * 2f; + } + if (NetworkServer.active && (bool)grappleController) + { + grappleController.projectileStickOnImpactController.Detach(); + grappleController.projectileStickOnImpactController.ignoreCharacters = true; + grappleController.projectileStickOnImpactController.ignoreWorld = true; + } + Collider component = GetComponent(); + if ((bool)component) + { + component.enabled = false; + } + } + + protected override void FixedUpdateBehavior() + { + base.FixedUpdateBehavior(); + if (!base.rigidbody) + { + return; + } + returnSpeed += returnSpeedAcceleration * Time.fixedDeltaTime; + base.rigidbody.velocity = (aimOrigin - position).normalized * returnSpeed; + if (NetworkServer.active) + { + Vector3 endPosition = position + base.rigidbody.velocity * Time.fixedDeltaTime; + if (HGMath.Overshoots(position, endPosition, aimOrigin)) + { + EntityState.Destroy(base.gameObject); + } + } + } + } + + private ProjectileController projectileController; + + private ProjectileStickOnImpact projectileStickOnImpactController; + + private ProjectileSimple projectileSimple; + + public SerializableEntityStateType ownerHookStateType; + + public float acceleration; + + public float lookAcceleration = 4f; + + public float lookAccelerationRampUpDuration = 0.25f; + + public float initialLookImpulse = 5f; + + public float initiallMoveImpulse = 5f; + + public float moveAcceleration = 4f; + + public string enterSoundString; + + public string exitSoundString; + + public string hookDistanceRTPCstring; + + public float minHookDistancePitchModifier; + + public float maxHookDistancePitchModifier; + + public AnimationCurve lookAccelerationRampUpCurve; + + public Transform ropeEndTransform; + + public string muzzleStringOnBody = "MuzzleLeft"; + + [Tooltip("The minimum distance the hook can be from the target before it detaches.")] + public float nearBreakDistance; + + [Tooltip("The maximum distance this hook can travel.")] + public float maxTravelDistance; + + public float escapeForceMultiplier = 2f; + + public float normalOffset = 1f; + + public float yankMassLimit; + + private Type resolvedOwnerHookStateType; + + private OwnerInfo owner; + + private bool didStick; + + private uint soundID; + + private void Awake() + { + projectileStickOnImpactController = GetComponent(); + projectileController = GetComponent(); + projectileSimple = GetComponent(); + resolvedOwnerHookStateType = ownerHookStateType.stateType; + if ((bool)ropeEndTransform) + { + soundID = Util.PlaySound(enterSoundString, ropeEndTransform.gameObject); + } + } + + private void FixedUpdate() + { + if ((bool)ropeEndTransform) + { + float in_value = Util.Remap((ropeEndTransform.transform.position - base.transform.position).magnitude, minHookDistancePitchModifier, maxHookDistancePitchModifier, 0f, 100f); + AkSoundEngine.SetRTPCValueByPlayingID(hookDistanceRTPCstring, in_value, soundID); + } + } + + private void AssignHookReferenceToBodyStateMachine() + { + if ((bool)owner.stateMachine && owner.stateMachine.state is FireHook fireHook) + { + fireHook.SetHookReference(base.gameObject); + } + Transform modelTransform = owner.gameObject.GetComponent().modelTransform; + if (!modelTransform) + { + return; + } + ChildLocator component = modelTransform.GetComponent(); + if ((bool)component) + { + Transform transform = component.FindChild(muzzleStringOnBody); + if ((bool)transform) + { + ropeEndTransform.SetParent(transform, worldPositionStays: false); + } + } + } + + private void Start() + { + owner = new OwnerInfo(projectileController.owner); + AssignHookReferenceToBodyStateMachine(); + } + + private void OnDestroy() + { + if ((bool)ropeEndTransform) + { + Util.PlaySound(exitSoundString, ropeEndTransform.gameObject); + UnityEngine.Object.Destroy(ropeEndTransform.gameObject); + } + else + { + AkSoundEngine.StopPlayingID(soundID); + } + } + + private bool OwnerIsInFiringState() + { + if ((bool)owner.stateMachine) + { + return owner.stateMachine.state.GetType() == resolvedOwnerHookStateType; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileHealOwnerOnDamageInflicted.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileHealOwnerOnDamageInflicted.cs new file mode 100644 index 0000000..6c438cd --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileHealOwnerOnDamageInflicted.cs @@ -0,0 +1,34 @@ +using RoR2.Orbs; +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileHealOwnerOnDamageInflicted : MonoBehaviour, IOnDamageInflictedServerReceiver +{ + public float fractionOfDamage; + + private ProjectileController projectileController; + + private void Awake() + { + projectileController = GetComponent(); + } + + public void OnDamageInflictedServer(DamageReport damageReport) + { + if ((bool)projectileController.owner) + { + HealthComponent component = projectileController.owner.GetComponent(); + if ((bool)component) + { + HealOrb healOrb = new HealOrb(); + healOrb.origin = base.transform.position; + healOrb.target = component.body.mainHurtBox; + healOrb.healValue = damageReport.damageDealt * fractionOfDamage; + healOrb.overrideDuration = 0.3f; + OrbManager.instance.AddOrb(healOrb); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactEvent.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactEvent.cs new file mode 100644 index 0000000..da0fac6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactEvent.cs @@ -0,0 +1,9 @@ +using System; +using UnityEngine.Events; + +namespace RoR2.Projectile; + +[Serializable] +public class ProjectileImpactEvent : UnityEvent +{ +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactEventCaller.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactEventCaller.cs new file mode 100644 index 0000000..4d4330f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactEventCaller.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileImpactEventCaller : MonoBehaviour, IProjectileImpactBehavior +{ + public ProjectileImpactEvent impactEvent; + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + impactEvent?.Invoke(impactInfo); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactExplosion.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactExplosion.cs new file mode 100644 index 0000000..f651844 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactExplosion.cs @@ -0,0 +1,192 @@ +using System; +using HG; +using RoR2.Audio; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileImpactExplosion : ProjectileExplosion, IProjectileImpactBehavior +{ + public enum TransformSpace + { + World, + Local, + Normal + } + + private Vector3 impactNormal = Vector3.up; + + [Header("Impact & Lifetime Properties")] + public GameObject impactEffect; + + [ShowFieldObsolete] + [Tooltip("This sound will not play over the network. Use lifetimeExpiredSound instead.")] + [HideInInspector] + [Obsolete("This sound will not play over the network. Use lifetimeExpiredSound instead.", false)] + public string lifetimeExpiredSoundString; + + public NetworkSoundEventDef lifetimeExpiredSound; + + public float offsetForLifetimeExpiredSound; + + public bool destroyOnEnemy = true; + + public bool destroyOnWorld; + + public bool impactOnWorld = true; + + public bool timerAfterImpact; + + public float lifetime; + + public float lifetimeAfterImpact; + + public float lifetimeRandomOffset; + + private float stopwatch; + + public uint minimumPhysicsStepsToKeepAliveAfterImpact; + + private float stopwatchAfterImpact; + + private bool hasImpact; + + private bool hasPlayedLifetimeExpiredSound; + + public TransformSpace transformSpace; + + public bool explodeOnLifeTimeExpiration; + + protected override void Awake() + { + base.Awake(); + lifetime += UnityEngine.Random.Range(0f, lifetimeRandomOffset); + } + + protected void FixedUpdate() + { + stopwatch += Time.fixedDeltaTime; + if (!NetworkServer.active && !projectileController.isPrediction) + { + return; + } + if (explodeOnLifeTimeExpiration && alive && stopwatch >= lifetime) + { + explosionEffect = impactEffect ?? explosionEffect; + Detonate(); + } + if (timerAfterImpact && hasImpact) + { + stopwatchAfterImpact += Time.fixedDeltaTime; + } + bool num = stopwatch >= lifetime; + bool flag = timerAfterImpact && stopwatchAfterImpact > lifetimeAfterImpact; + bool flag2 = (bool)projectileHealthComponent && !projectileHealthComponent.alive; + if (num || flag || flag2) + { + alive = false; + } + if (timerAfterImpact && hasImpact && minimumPhysicsStepsToKeepAliveAfterImpact != 0) + { + minimumPhysicsStepsToKeepAliveAfterImpact--; + alive = true; + } + if (alive && !hasPlayedLifetimeExpiredSound) + { + bool flag3 = stopwatch > lifetime - offsetForLifetimeExpiredSound; + if (timerAfterImpact) + { + flag3 |= stopwatchAfterImpact > lifetimeAfterImpact - offsetForLifetimeExpiredSound; + } + if (flag3) + { + hasPlayedLifetimeExpiredSound = true; + if (NetworkServer.active && (bool)lifetimeExpiredSound) + { + PointSoundManager.EmitSoundServer(lifetimeExpiredSound.index, base.transform.position); + } + } + } + if (!alive) + { + explosionEffect = impactEffect ?? explosionEffect; + Detonate(); + } + } + + protected override Quaternion GetRandomDirectionForChild() + { + Quaternion randomChildRollPitch = GetRandomChildRollPitch(); + return transformSpace switch + { + TransformSpace.Local => base.transform.rotation * randomChildRollPitch, + TransformSpace.Normal => Quaternion.FromToRotation(Vector3.forward, impactNormal) * randomChildRollPitch, + _ => randomChildRollPitch, + }; + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (!alive) + { + return; + } + Collider collider = impactInfo.collider; + impactNormal = impactInfo.estimatedImpactNormal; + if (!collider) + { + return; + } + DamageInfo damageInfo = new DamageInfo(); + if ((bool)projectileDamage) + { + damageInfo.damage = projectileDamage.damage; + damageInfo.crit = projectileDamage.crit; + damageInfo.attacker = (projectileController.owner ? projectileController.owner.gameObject : null); + damageInfo.inflictor = base.gameObject; + damageInfo.position = impactInfo.estimatedPointOfImpact; + damageInfo.force = projectileDamage.force * base.transform.forward; + damageInfo.procChainMask = projectileController.procChainMask; + damageInfo.procCoefficient = projectileController.procCoefficient; + } + HurtBox component = collider.GetComponent(); + if ((bool)component) + { + if (destroyOnEnemy) + { + HealthComponent healthComponent = component.healthComponent; + if ((bool)healthComponent) + { + if (healthComponent.gameObject == projectileController.owner || ((bool)projectileHealthComponent && healthComponent == projectileHealthComponent)) + { + return; + } + alive = false; + } + } + } + else if (destroyOnWorld) + { + alive = false; + } + hasImpact = (bool)component || impactOnWorld; + if (NetworkServer.active && hasImpact) + { + GlobalEventManager.instance.OnHitAll(damageInfo, collider.gameObject); + } + } + + protected override void OnValidate() + { + if (!Application.IsPlaying(this)) + { + base.OnValidate(); + if (!string.IsNullOrEmpty(lifetimeExpiredSoundString)) + { + Debug.LogWarningFormat(base.gameObject, "{0} ProjectileImpactExplosion component supplies a value in the lifetimeExpiredSoundString field. This will not play correctly over the network. Please use lifetimeExpiredSound instead.", Util.GetGameObjectHierarchyName(base.gameObject)); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactInfo.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactInfo.cs new file mode 100644 index 0000000..d42ada9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpactInfo.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public struct ProjectileImpactInfo +{ + public Collider collider; + + public Vector3 estimatedPointOfImpact; + + public Vector3 estimatedImpactNormal; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpaleOnEnemy.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpaleOnEnemy.cs new file mode 100644 index 0000000..1285fef --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileImpaleOnEnemy.cs @@ -0,0 +1,45 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileImpaleOnEnemy : MonoBehaviour, IProjectileImpactBehavior +{ + private bool alive = true; + + public GameObject impalePrefab; + + private Rigidbody rigidbody; + + private void Awake() + { + rigidbody = GetComponent(); + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (!alive) + { + return; + } + Collider collider = impactInfo.collider; + if (!collider) + { + return; + } + HurtBox component = collider.GetComponent(); + if ((bool)component) + { + _ = base.transform.position; + Vector3 estimatedPointOfImpact = impactInfo.estimatedPointOfImpact; + _ = Quaternion.identity; + if ((bool)rigidbody) + { + Util.QuaternionSafeLookRotation(rigidbody.velocity); + } + GameObject obj = Object.Instantiate(impalePrefab, component.transform); + obj.transform.position = estimatedPointOfImpact; + obj.transform.rotation = base.transform.rotation; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileInflictTimedBuff.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileInflictTimedBuff.cs new file mode 100644 index 0000000..d876e61 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileInflictTimedBuff.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public class ProjectileInflictTimedBuff : MonoBehaviour, IOnDamageInflictedServerReceiver +{ + public BuffDef buffDef; + + public float duration; + + public void OnDamageInflictedServer(DamageReport damageReport) + { + CharacterBody victimBody = damageReport.victimBody; + if ((bool)victimBody) + { + victimBody.AddTimedBuff(buffDef.buffIndex, duration); + } + } + + private void OnValidate() + { + if (!buffDef) + { + Debug.LogWarningFormat(this, "ProjectileInflictTimedBuff {0} has no buff specified.", this); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileInstantiateDeployable.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileInstantiateDeployable.cs new file mode 100644 index 0000000..340a4e3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileInstantiateDeployable.cs @@ -0,0 +1,67 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileInstantiateDeployable : MonoBehaviour +{ + [Tooltip("The deployable slot to use.")] + [SerializeField] + private DeployableSlot deployableSlot; + + [Tooltip("The prefab to instantiate.")] + [SerializeField] + private GameObject prefab; + + [Tooltip("The object upon which the prefab will be positioned.")] + [SerializeField] + private Transform targetTransform; + + [SerializeField] + [Tooltip("The transform upon which to instantiate the prefab.")] + private bool copyTargetRotation; + + [Tooltip("Whether or not to parent the instantiated prefab to the specified transform.")] + [SerializeField] + private bool parentToTarget; + + [SerializeField] + [Tooltip("Whether or not to instantiate this prefab. If so, this will only run on the server, and will be spawned over the network.")] + private bool instantiateOnStart = true; + + public void Start() + { + if (instantiateOnStart) + { + InstantiateDeployable(); + } + } + + public void InstantiateDeployable() + { + if (!NetworkServer.active) + { + return; + } + GameObject owner = GetComponent().owner; + if (!owner) + { + return; + } + CharacterBody component = owner.GetComponent(); + if ((bool)component) + { + CharacterMaster master = component.master; + if ((bool)master) + { + Vector3 position = (targetTransform ? targetTransform.position : Vector3.zero); + Quaternion rotation = (copyTargetRotation ? targetTransform.rotation : Quaternion.identity); + Transform parent = (parentToTarget ? targetTransform : null); + GameObject gameObject = Object.Instantiate(prefab, position, rotation, parent); + NetworkServer.Spawn(gameObject); + master.AddDeployable(gameObject.GetComponent(), deployableSlot); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileIntervalOverlapAttack.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileIntervalOverlapAttack.cs new file mode 100644 index 0000000..5deb86f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileIntervalOverlapAttack.cs @@ -0,0 +1,58 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileDamage))] +[RequireComponent(typeof(ProjectileController))] +public class ProjectileIntervalOverlapAttack : MonoBehaviour +{ + public HitBoxGroup hitBoxGroup; + + public float interval; + + public float damageCoefficient = 1f; + + private float countdown; + + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + } + + private void Start() + { + countdown = 0f; + } + + private void FixedUpdate() + { + if (!NetworkServer.active) + { + return; + } + countdown -= Time.fixedDeltaTime; + if (countdown <= 0f) + { + countdown += interval; + if ((bool)hitBoxGroup) + { + OverlapAttack overlapAttack = new OverlapAttack(); + overlapAttack.attacker = projectileController.owner; + overlapAttack.inflictor = base.gameObject; + overlapAttack.teamIndex = projectileController.teamFilter.teamIndex; + overlapAttack.damage = projectileDamage.damage * damageCoefficient; + overlapAttack.hitBoxGroup = hitBoxGroup; + overlapAttack.isCrit = projectileDamage.crit; + overlapAttack.procCoefficient = 0f; + overlapAttack.damageType = projectileDamage.damageType; + overlapAttack.Fire(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileMageFirewallController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileMageFirewallController.cs new file mode 100644 index 0000000..18214bd --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileMageFirewallController.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileDamage))] +public class ProjectileMageFirewallController : MonoBehaviour, IProjectileImpactBehavior +{ + public GameObject walkerPrefab; + + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private bool consumed; + + private void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + } + + void IProjectileImpactBehavior.OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (!consumed) + { + consumed = true; + CreateWalkers(); + Object.Destroy(base.gameObject); + } + } + + private void CreateWalkers() + { + Vector3 forward = base.transform.forward; + forward.y = 0f; + forward.Normalize(); + Vector3 vector = Vector3.Cross(Vector3.up, forward); + ProjectileManager.instance.FireProjectile(walkerPrefab, base.transform.position + Vector3.up, Util.QuaternionSafeLookRotation(vector), projectileController.owner, projectileDamage.damage, projectileDamage.force, projectileDamage.crit, projectileDamage.damageColorIndex); + ProjectileManager.instance.FireProjectile(walkerPrefab, base.transform.position + Vector3.up, Util.QuaternionSafeLookRotation(-vector), projectileController.owner, projectileDamage.damage, projectileDamage.force, projectileDamage.crit, projectileDamage.damageColorIndex); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileMageFirewallWalkerController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileMageFirewallWalkerController.cs new file mode 100644 index 0000000..6c51d5a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileMageFirewallWalkerController.cs @@ -0,0 +1,128 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileDamage))] +[RequireComponent(typeof(ProjectileController))] +public class ProjectileMageFirewallWalkerController : MonoBehaviour +{ + public int totalProjectiles; + + private int _projectileCounter; + + public float dropInterval = 0.15f; + + public GameObject firePillarPrefab; + + public float pillarAngle = 45f; + + public bool curveToCenter = true; + + private float moveSign; + + [Tooltip("Some consoles/etc run a different FixedUpdate timestep. This allows you to run an independent coroutine to get the timing right.")] + [SerializeField] + private bool DontUseFixedUpdateForProjectileSpawning; + + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private Vector3 lastCenterPosition; + + private float timer; + + private Vector3 currentPillarVector = Vector3.up; + + private void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + lastCenterPosition = base.transform.position; + timer = dropInterval / 2f; + moveSign = 1f; + } + + private void Start() + { + if ((bool)projectileController.owner) + { + Vector3 position = projectileController.owner.transform.position; + Vector3 rhs = base.transform.position - position; + rhs.y = 0f; + if (rhs.x != 0f && rhs.z != 0f) + { + moveSign = Mathf.Sign(Vector3.Dot(base.transform.right, rhs)); + } + } + UpdateDirections(); + _projectileCounter = totalProjectiles; + if (DontUseFixedUpdateForProjectileSpawning) + { + StartCoroutine(ProcessProjectilesLoop()); + } + } + + private void UpdateDirections() + { + if (curveToCenter) + { + Vector3 vector = base.transform.position - lastCenterPosition; + vector.y = 0f; + if (vector.x != 0f && vector.z != 0f) + { + vector.Normalize(); + Vector3 vector2 = Vector3.Cross(Vector3.up, vector); + base.transform.forward = vector2 * moveSign; + currentPillarVector = Quaternion.AngleAxis(pillarAngle, vector2) * Vector3.Cross(vector, vector2); + } + } + } + + private IEnumerator ProcessProjectilesLoop() + { + yield return new WaitForSeconds(dropInterval / 2f); + while (base.gameObject.activeSelf) + { + HandleProjectileGeneration(); + yield return new WaitForSeconds(dropInterval); + } + } + + private void FixedUpdate() + { + if (!DontUseFixedUpdateForProjectileSpawning) + { + HandleProjectileGeneration(); + } + } + + private void HandleProjectileGeneration() + { + if ((bool)projectileController.owner) + { + lastCenterPosition = projectileController.owner.transform.position; + } + if (_projectileCounter <= 0) + { + return; + } + UpdateDirections(); + if (!NetworkServer.active) + { + return; + } + timer -= Time.fixedDeltaTime; + if (timer <= 0f || DontUseFixedUpdateForProjectileSpawning) + { + timer = dropInterval; + _projectileCounter--; + if ((bool)firePillarPrefab) + { + ProjectileManager.instance.FireProjectile(firePillarPrefab, base.transform.position, Util.QuaternionSafeLookRotation(currentPillarVector), projectileController.owner, projectileDamage.damage, projectileDamage.force, projectileDamage.crit, projectileDamage.damageColorIndex); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileManager.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileManager.cs new file mode 100644 index 0000000..f2d196e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileManager.cs @@ -0,0 +1,573 @@ +using System.Collections.Generic; +using RoR2.Networking; +using Unity; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +public class ProjectileManager : MonoBehaviour +{ + private struct ProjectileQueueItem + { + public FireProjectileInfo fireProjectileInfo; + + public NetworkConnection clientAuthorityOwner; + + public NetworkClient localNetworkClient; + + public ushort predictionId; + + public double fireSendTime; + + public int timeCachedFrameStamp; + + public Vector3 positionOffset; + + public bool ownerStartedAsNull; + + public ProjectileQueueItem(FireProjectileInfo fireProjectileInfo, int currentFrame, NetworkConnection clientAuthorityOwner = null, ushort predictionId = 0, double fireSendTime = 0.0) + { + this.fireProjectileInfo = fireProjectileInfo; + ownerStartedAsNull = fireProjectileInfo.owner == null; + timeCachedFrameStamp = currentFrame; + this.clientAuthorityOwner = clientAuthorityOwner; + this.predictionId = predictionId; + this.fireSendTime = fireSendTime; + localNetworkClient = null; + if (!ownerStartedAsNull && fireProjectileInfo.owner.TryGetComponent(out var component)) + { + positionOffset = component.corePosition - fireProjectileInfo.position; + } + else + { + positionOffset = Vector3.zero; + } + } + + public ProjectileQueueItem(FireProjectileInfo fireProjectileInfo, NetworkClient serverClient = null, double fireSendTime = 0.0) + { + this.fireProjectileInfo = fireProjectileInfo; + ownerStartedAsNull = fireProjectileInfo.owner == null; + timeCachedFrameStamp = 0; + clientAuthorityOwner = null; + predictionId = 0; + this.fireSendTime = fireSendTime; + localNetworkClient = serverClient; + if (!ownerStartedAsNull && fireProjectileInfo.owner.TryGetComponent(out var component)) + { + positionOffset = component.corePosition - fireProjectileInfo.position; + } + else + { + positionOffset = Vector3.zero; + } + } + + public void TryAdjustingFiringPosition() + { + if (!ownerStartedAsNull && !(fireProjectileInfo.owner == null) && fireProjectileInfo.owner.TryGetComponent(out var component)) + { + fireProjectileInfo.position = component.corePosition + positionOffset; + } + } + } + + private class PlayerFireProjectileMessage : MessageBase + { + public double sendTime; + + public uint prefabIndexPlusOne; + + public Vector3 position; + + public Quaternion rotation; + + public GameObject owner; + + public HurtBoxReference target; + + public float damage; + + public float force; + + public bool crit; + + public ushort predictionId; + + public DamageColorIndex damageColorIndex; + + public float speedOverride; + + public float fuseOverride; + + public bool useDamageTypeOverride; + + public DamageTypeCombo damageTypeOverride; + + public override void Serialize(NetworkWriter writer) + { + writer.Write(sendTime); + writer.WritePackedUInt32(prefabIndexPlusOne); + writer.Write(position); + writer.Write(rotation); + writer.Write(owner); + GeneratedNetworkCode._WriteHurtBoxReference_None(writer, target); + writer.Write(damage); + writer.Write(force); + writer.Write(crit); + writer.WritePackedUInt32(predictionId); + writer.Write((int)damageColorIndex); + writer.Write(speedOverride); + writer.Write(fuseOverride); + writer.Write(useDamageTypeOverride); + GeneratedNetworkCode._WriteDamageTypeCombo_None(writer, damageTypeOverride); + } + + public override void Deserialize(NetworkReader reader) + { + sendTime = reader.ReadDouble(); + prefabIndexPlusOne = reader.ReadPackedUInt32(); + position = reader.ReadVector3(); + rotation = reader.ReadQuaternion(); + owner = reader.ReadGameObject(); + target = GeneratedNetworkCode._ReadHurtBoxReference_None(reader); + damage = reader.ReadSingle(); + force = reader.ReadSingle(); + crit = reader.ReadBoolean(); + predictionId = (ushort)reader.ReadPackedUInt32(); + damageColorIndex = (DamageColorIndex)reader.ReadInt32(); + speedOverride = reader.ReadSingle(); + fuseOverride = reader.ReadSingle(); + useDamageTypeOverride = reader.ReadBoolean(); + damageTypeOverride = GeneratedNetworkCode._ReadDamageTypeCombo_None(reader); + } + } + + private class ReleasePredictionIdMessage : MessageBase + { + public ushort predictionId; + + public override void Serialize(NetworkWriter writer) + { + writer.WritePackedUInt32(predictionId); + } + + public override void Deserialize(NetworkReader reader) + { + predictionId = (ushort)reader.ReadPackedUInt32(); + } + } + + private class PredictionManager + { + private Dictionary predictions = new Dictionary(); + + public ProjectileController FindPredictedProjectileController(ushort predictionId) + { + return predictions[predictionId]; + } + + public void OnAuthorityProjectileReceived(ProjectileController authoritativeProjectile) + { + if (authoritativeProjectile.hasAuthority && authoritativeProjectile.predictionId != 0 && predictions.TryGetValue(authoritativeProjectile.predictionId, out var value)) + { + authoritativeProjectile.ghost = value.ghost; + if ((bool)authoritativeProjectile.ghost) + { + authoritativeProjectile.ghost.authorityTransform = authoritativeProjectile.transform; + } + authoritativeProjectile.DispatchOnInitialized(); + } + } + + public void ReleasePredictionId(ushort predictionId) + { + ProjectileController projectileController = predictions[predictionId]; + predictions.Remove(predictionId); + if ((bool)projectileController && (bool)projectileController.gameObject) + { + Object.Destroy(projectileController.gameObject); + } + } + + public void RegisterPrediction(ProjectileController predictedProjectile) + { + predictedProjectile.NetworkpredictionId = RequestPredictionId(); + predictions[predictedProjectile.predictionId] = predictedProjectile; + predictedProjectile.isPrediction = true; + } + + private ushort RequestPredictionId() + { + for (ushort num = 1; num < 32767; num++) + { + if (!predictions.ContainsKey(num)) + { + return num; + } + } + return 0; + } + } + + private PredictionManager predictionManager; + + private static Queue queuedProjectiles = new Queue(150); + + private static int _projectileCurrentFrame; + + private static int totalProjectilesFiredThisFrame; + + private static int maximumProjectilesFiredPerFrame = 20; + + private static int totalQueuedProjectilesAllowedPerFrame = 5; + + private static double projectileExpirationLifetime = 5.0; + + private PlayerFireProjectileMessage fireMsg = new PlayerFireProjectileMessage(); + + private ReleasePredictionIdMessage releasePredictionIdMsg = new ReleasePredictionIdMessage(); + + public static ProjectileManager instance { get; private set; } + + private static int projectileCurrentFrame + { + get + { + return _projectileCurrentFrame; + } + set + { + if (value > _projectileCurrentFrame) + { + _projectileCurrentFrame = value; + totalProjectilesFiredThisFrame = 0; + } + } + } + + private static void CacheProjectileForNextFrameServer(FireProjectileInfo fireProjectileInfo, NetworkConnection clientAuthorityOwner = null, ushort predictionId = 0, double fastForwardTime = 0.0) + { + ProjectileQueueItem item = new ProjectileQueueItem(fireProjectileInfo, projectileCurrentFrame, clientAuthorityOwner, predictionId, (double)Run.instance.time - fastForwardTime); + queuedProjectiles.Enqueue(item); + } + + private static void CacheProjectileForNextFrameClient(FireProjectileInfo fireProjectileInfo, NetworkClient client = null, double fireTime = 0.0) + { + ProjectileQueueItem item = new ProjectileQueueItem(fireProjectileInfo, client, fireTime); + queuedProjectiles.Enqueue(item); + } + + private static bool CanAffordToFireProjectile() + { + return totalProjectilesFiredThisFrame < maximumProjectilesFiredPerFrame; + } + + private bool ShouldSkipFiringProjectile(double currentRunTime, ProjectileQueueItem nextItem) + { + if (!(currentRunTime - nextItem.fireSendTime > projectileExpirationLifetime)) + { + if (!nextItem.ownerStartedAsNull) + { + return nextItem.fireProjectileInfo.owner == null; + } + return false; + } + return true; + } + + private void ClientFireQueuedProjectiles() + { + double currentRunTime = Run.instance.time; + int num = 0; + int num2 = 0; + num2 = 0; + while (totalProjectilesFiredThisFrame < maximumProjectilesFiredPerFrame && queuedProjectiles.Count > 0 && num2 < totalQueuedProjectilesAllowedPerFrame) + { + ProjectileQueueItem nextItem = queuedProjectiles.Dequeue(); + if (ShouldSkipFiringProjectile(currentRunTime, nextItem)) + { + num++; + num2--; + } + else + { + nextItem.TryAdjustingFiringPosition(); + FireProjectileClient(nextItem.fireProjectileInfo, nextItem.localNetworkClient, nextItem.fireSendTime); + } + num2++; + } + _ = 0; + _ = 0; + } + + private void ServerFireQueuedProjectiles() + { + double num = Run.instance.time; + int num2 = 0; + int num3 = 0; + num3 = 0; + while (totalProjectilesFiredThisFrame < maximumProjectilesFiredPerFrame && queuedProjectiles.Count > 0 && num3 < totalQueuedProjectilesAllowedPerFrame) + { + ProjectileQueueItem nextItem = queuedProjectiles.Dequeue(); + if (ShouldSkipFiringProjectile(num, nextItem)) + { + num2++; + num3--; + } + else + { + nextItem.TryAdjustingFiringPosition(); + FireProjectileServer(nextItem.fireProjectileInfo, nextItem.clientAuthorityOwner, nextItem.predictionId, num - nextItem.fireSendTime); + } + num3++; + } + _ = 0; + _ = 0; + } + + private void Awake() + { + predictionManager = new PredictionManager(); + } + + private void OnEnable() + { + instance = SingletonHelper.Assign(instance, this); + } + + private void OnDisable() + { + instance = SingletonHelper.Unassign(instance, this); + } + + [NetworkMessageHandler(msgType = 49, server = true)] + private static void HandlePlayerFireProjectile(NetworkMessage netMsg) + { + if ((bool)instance) + { + instance.HandlePlayerFireProjectileInternal(netMsg); + } + } + + [NetworkMessageHandler(msgType = 50, client = true)] + private static void HandleReleaseProjectilePredictionId(NetworkMessage netMsg) + { + if ((bool)instance) + { + instance.HandleReleaseProjectilePredictionIdInternal(netMsg); + } + } + + public void FireProjectile(GameObject prefab, Vector3 position, Quaternion rotation, GameObject owner, float damage, float force, bool crit, DamageColorIndex damageColorIndex = DamageColorIndex.Default, GameObject target = null, float speedOverride = -1f) + { + FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); + fireProjectileInfo.projectilePrefab = prefab; + fireProjectileInfo.position = position; + fireProjectileInfo.rotation = rotation; + fireProjectileInfo.owner = owner; + fireProjectileInfo.damage = damage; + fireProjectileInfo.force = force; + fireProjectileInfo.crit = crit; + fireProjectileInfo.damageColorIndex = damageColorIndex; + fireProjectileInfo.target = target; + fireProjectileInfo.speedOverride = speedOverride; + fireProjectileInfo.fuseOverride = -1f; + fireProjectileInfo.damageTypeOverride = null; + FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; + FireProjectile(fireProjectileInfo2); + } + + public void FireProjectile(FireProjectileInfo fireProjectileInfo) + { + if (NetworkServer.active) + { + FireProjectileServer(fireProjectileInfo, null, 0); + } + else + { + FireProjectileClient(fireProjectileInfo, NetworkManager.singleton.client); + } + } + + private void FireProjectileClient(FireProjectileInfo fireProjectileInfo, NetworkClient client, double fireTime = -1.0) + { + if (fireTime == -1.0) + { + fireTime = Run.instance.time; + } + int projectileIndex = ProjectileCatalog.GetProjectileIndex(fireProjectileInfo.projectilePrefab); + if (projectileIndex == -1) + { + Debug.LogErrorFormat(fireProjectileInfo.projectilePrefab, "Prefab {0} is not a registered projectile prefab.", fireProjectileInfo.projectilePrefab); + return; + } + bool allowPrediction = ProjectileCatalog.GetProjectilePrefabProjectileControllerComponent(projectileIndex).allowPrediction; + ushort predictionId = 0; + if (allowPrediction) + { + ProjectileController component = Object.Instantiate(fireProjectileInfo.projectilePrefab, fireProjectileInfo.position, fireProjectileInfo.rotation).GetComponent(); + InitializeProjectile(component, fireProjectileInfo); + predictionManager.RegisterPrediction(component); + predictionId = component.predictionId; + } + fireMsg.sendTime = fireTime; + fireMsg.prefabIndexPlusOne = Util.IntToUintPlusOne(projectileIndex); + fireMsg.position = fireProjectileInfo.position; + fireMsg.rotation = fireProjectileInfo.rotation; + fireMsg.owner = fireProjectileInfo.owner; + fireMsg.predictionId = predictionId; + fireMsg.damage = fireProjectileInfo.damage; + fireMsg.force = fireProjectileInfo.force; + fireMsg.crit = fireProjectileInfo.crit; + fireMsg.damageColorIndex = fireProjectileInfo.damageColorIndex; + fireMsg.speedOverride = fireProjectileInfo.speedOverride; + fireMsg.fuseOverride = fireProjectileInfo.fuseOverride; + fireMsg.useDamageTypeOverride = fireProjectileInfo.damageTypeOverride.HasValue; + fireMsg.damageTypeOverride = fireProjectileInfo.damageTypeOverride ?? ((DamageTypeCombo)DamageType.Generic); + if ((bool)fireProjectileInfo.target) + { + HurtBox component2 = fireProjectileInfo.target.GetComponent(); + fireMsg.target = (component2 ? HurtBoxReference.FromHurtBox(component2) : HurtBoxReference.FromRootObject(fireProjectileInfo.target)); + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(49); + networkWriter.Write(fireMsg); + networkWriter.FinishMessage(); + client.SendWriter(networkWriter, 0); + } + + private static void InitializeProjectile(ProjectileController projectileController, FireProjectileInfo fireProjectileInfo) + { + GameObject gameObject = projectileController.gameObject; + ProjectileDamage component = gameObject.GetComponent(); + TeamFilter component2 = gameObject.GetComponent(); + ProjectileNetworkTransform component3 = gameObject.GetComponent(); + ProjectileTargetComponent component4 = gameObject.GetComponent(); + ProjectileSimple component5 = gameObject.GetComponent(); + projectileController.Networkowner = fireProjectileInfo.owner; + projectileController.procChainMask = fireProjectileInfo.procChainMask; + if ((bool)component2) + { + component2.teamIndex = TeamComponent.GetObjectTeam(fireProjectileInfo.owner); + } + if ((bool)component3) + { + component3.SetValuesFromTransform(); + } + if ((bool)component4 && (bool)fireProjectileInfo.target) + { + CharacterBody component6 = fireProjectileInfo.target.GetComponent(); + component4.target = (component6 ? component6.coreTransform : fireProjectileInfo.target.transform); + } + if (fireProjectileInfo.useSpeedOverride && (bool)component5) + { + component5.desiredForwardSpeed = fireProjectileInfo.speedOverride; + } + if (fireProjectileInfo.useFuseOverride) + { + ProjectileImpactExplosion component7 = gameObject.GetComponent(); + if ((bool)component7) + { + component7.lifetime = fireProjectileInfo.fuseOverride; + } + ProjectileFuse component8 = gameObject.GetComponent(); + if ((bool)component8) + { + component8.fuse = fireProjectileInfo.fuseOverride; + } + } + if ((bool)component) + { + component.damage = fireProjectileInfo.damage; + component.force = fireProjectileInfo.force; + component.crit = fireProjectileInfo.crit; + component.damageColorIndex = fireProjectileInfo.damageColorIndex; + if (fireProjectileInfo.damageTypeOverride.HasValue) + { + component.damageType = fireProjectileInfo.damageTypeOverride.Value; + } + } + projectileController.DispatchOnInitialized(); + } + + private void FireProjectileServer(FireProjectileInfo fireProjectileInfo, NetworkConnection clientAuthorityOwner = null, ushort predictionId = 0, double fastForwardTime = 0.0) + { + GameObject gameObject = Object.Instantiate(fireProjectileInfo.projectilePrefab, fireProjectileInfo.position, fireProjectileInfo.rotation); + ProjectileController component = gameObject.GetComponent(); + component.NetworkpredictionId = predictionId; + InitializeProjectile(component, fireProjectileInfo); + NetworkIdentity component2 = gameObject.GetComponent(); + if (clientAuthorityOwner != null && component2.localPlayerAuthority) + { + NetworkServer.SpawnWithClientAuthority(gameObject, clientAuthorityOwner); + } + else + { + NetworkServer.Spawn(gameObject); + } + } + + public void OnServerProjectileDestroyed(ProjectileController projectile) + { + if (projectile.predictionId != 0) + { + NetworkConnection clientAuthorityOwner = projectile.clientAuthorityOwner; + if (clientAuthorityOwner != null) + { + ReleasePredictionId(clientAuthorityOwner, projectile.predictionId); + } + } + } + + public void OnClientProjectileReceived(ProjectileController projectile) + { + if (projectile.predictionId != 0 && projectile.hasAuthority) + { + predictionManager.OnAuthorityProjectileReceived(projectile); + } + } + + private void ReleasePredictionId(NetworkConnection owner, ushort predictionId) + { + releasePredictionIdMsg.predictionId = predictionId; + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(50); + networkWriter.Write(releasePredictionIdMsg); + networkWriter.FinishMessage(); + owner.SendWriter(networkWriter, 0); + } + + private void HandlePlayerFireProjectileInternal(NetworkMessage netMsg) + { + netMsg.ReadMessage(fireMsg); + GameObject projectilePrefab = ProjectileCatalog.GetProjectilePrefab(Util.UintToIntMinusOne(fireMsg.prefabIndexPlusOne)); + if (projectilePrefab == null) + { + ReleasePredictionId(netMsg.conn, fireMsg.predictionId); + return; + } + FireProjectileServer(new FireProjectileInfo + { + projectilePrefab = projectilePrefab, + position = fireMsg.position, + rotation = fireMsg.rotation, + owner = fireMsg.owner, + damage = fireMsg.damage, + force = fireMsg.force, + crit = fireMsg.crit, + target = fireMsg.target.ResolveGameObject(), + damageColorIndex = fireMsg.damageColorIndex, + speedOverride = fireMsg.speedOverride, + fuseOverride = fireMsg.fuseOverride, + damageTypeOverride = (fireMsg.useDamageTypeOverride ? new DamageTypeCombo?(fireMsg.damageTypeOverride) : null) + }, netMsg.conn, fireMsg.predictionId, (double)Run.instance.time - fireMsg.sendTime); + } + + private void HandleReleaseProjectilePredictionIdInternal(NetworkMessage netMsg) + { + netMsg.ReadMessage(releasePredictionIdMsg); + predictionManager.ReleasePredictionId(releasePredictionIdMsg.predictionId); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileNetworkTransform.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileNetworkTransform.cs new file mode 100644 index 0000000..76ef481 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileNetworkTransform.cs @@ -0,0 +1,371 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +public class ProjectileNetworkTransform : NetworkBehaviour +{ + private ProjectileController projectileController; + + private new Transform transform; + + private Rigidbody rb; + + private InterpolatedTransform interpolatedTransform; + + [Tooltip("The delay in seconds between position network updates.")] + public float positionTransmitInterval = 1f / 30f; + + [Tooltip("The number of packets of buffers to have.")] + public float interpolationFactor = 1f; + + public bool allowClientsideCollision; + + public bool checkForLocalPlayerAuthority; + + public int singletonArrayIndex = -1; + + private bool hasEffectiveAuthority; + + [SyncVar(hook = "OnSyncPosition")] + public Vector3 serverPosition; + + [SyncVar(hook = "OnSyncRotation")] + public Quaternion serverRotation; + + private NetworkLerpedVector3 interpolatedPosition; + + private NetworkLerpedQuaternion interpolatedRotation; + + private bool needsUpdate = true; + + private static int kCmdCmdSetPositionAndRotationFromClient; + + private bool isPrediction + { + get + { + if (!projectileController) + { + return false; + } + return projectileController.isPrediction; + } + } + + public Vector3 NetworkserverPosition + { + get + { + return serverPosition; + } + [param: In] + set + { + if (NetworkServer.localClientActive && !base.syncVarHookGuard) + { + base.syncVarHookGuard = true; + OnSyncPosition(value); + base.syncVarHookGuard = false; + } + SetSyncVar(value, ref serverPosition, 1u); + } + } + + public Quaternion NetworkserverRotation + { + get + { + return serverRotation; + } + [param: In] + set + { + if (NetworkServer.localClientActive && !base.syncVarHookGuard) + { + base.syncVarHookGuard = true; + OnSyncRotation(value); + base.syncVarHookGuard = false; + } + SetSyncVar(value, ref serverRotation, 2u); + } + } + + public void SetValuesFromTransform() + { + NetworkserverPosition = transform.position; + NetworkserverRotation = transform.rotation; + if (singletonArrayIndex != -1) + { + Debug.LogError("SetValuesFromTransform called without being registered!"); + } + needsUpdate = true; + } + + private void Awake() + { + projectileController = GetComponent(); + interpolatedTransform = GetComponent(); + transform = base.transform; + NetworkserverPosition = transform.position; + NetworkserverRotation = transform.rotation; + rb = GetComponent(); + } + + private void Start() + { + interpolatedPosition.interpDelay = GetNetworkSendInterval() * interpolationFactor; + interpolatedPosition.SetValueImmediate(serverPosition); + interpolatedRotation.SetValueImmediate(serverRotation); + if (isPrediction) + { + base.enabled = false; + } + CheckAuthority(); + } + + private void CheckAuthority() + { + if (checkForLocalPlayerAuthority) + { + hasEffectiveAuthority = Util.HasEffectiveAuthority(base.gameObject); + } + else + { + hasEffectiveAuthority = NetworkServer.active; + } + if ((bool)rb && !isPrediction && !hasEffectiveAuthority) + { + rb.collisionDetectionMode = CollisionDetectionMode.Discrete; + rb.detectCollisions = allowClientsideCollision; + rb.isKinematic = true; + } + base.OnStartAuthority(); + } + + private void OnSyncPosition(Vector3 newPosition) + { + interpolatedPosition.PushValue(newPosition); + NetworkserverPosition = newPosition; + } + + [Command] + private void CmdSetPositionAndRotationFromClient(Vector3 position, Quaternion rotation) + { + NetworkserverPosition = position; + NetworkserverRotation = rotation; + } + + private void OnSyncRotation(Quaternion newRotation) + { + interpolatedRotation.PushValue(newRotation); + NetworkserverRotation = newRotation; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override float GetNetworkSendInterval() + { + return positionTransmitInterval; + } + + private void FixedUpdate() + { + MyFixedUpdate(Time.deltaTime); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool NeedsUpdate() + { + if (needsUpdate) + { + return true; + } + if (!(serverPosition != transform.position)) + { + return serverRotation != transform.rotation; + } + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CheckForUpdateAndPushUpdatesIfNeeded() + { + if (NeedsUpdate()) + { + interpolatedPosition.interpDelay = GetNetworkSendInterval() * interpolationFactor; + Transform obj = transform; + Vector3 position = obj.position; + Quaternion rotation = obj.rotation; + NetworkserverPosition = position; + NetworkserverRotation = rotation; + interpolatedPosition.SetValueImmediate(position); + interpolatedRotation.SetValueImmediate(rotation); + needsUpdate = false; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CheckForUpdateAndPushUpdatesIfNeededWithCommand() + { + if (NeedsUpdate()) + { + interpolatedPosition.interpDelay = GetNetworkSendInterval() * interpolationFactor; + Transform obj = transform; + Vector3 position = obj.position; + Quaternion rotation = obj.rotation; + CallCmdSetPositionAndRotationFromClient(position, rotation); + interpolatedPosition.SetValueImmediate(position); + interpolatedRotation.SetValueImmediate(rotation); + needsUpdate = false; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Interpolate() + { + Vector3 currentValue = interpolatedPosition.GetCurrentValue(hasAuthority: false); + Quaternion currentValue2 = interpolatedRotation.GetCurrentValue(hasAuthority: false); + ApplyPositionAndRotation(currentValue, currentValue2); + } + + private void MyFixedUpdate(float deltaTime) + { + if (checkForLocalPlayerAuthority) + { + if (hasEffectiveAuthority) + { + CheckForUpdateAndPushUpdatesIfNeededWithCommand(); + } + else + { + Interpolate(); + } + } + else if (base.isServer) + { + CheckForUpdateAndPushUpdatesIfNeeded(); + } + else + { + Interpolate(); + } + } + + private void ApplyPositionAndRotation(Vector3 position, Quaternion rotation) + { + if ((bool)rb && !interpolatedTransform) + { + rb.MovePosition(position); + rb.MoveRotation(rotation); + } + else + { + transform.position = position; + transform.rotation = rotation; + } + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdSetPositionAndRotationFromClient(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdSetPositionAndRotationFromClient called on client."); + } + else + { + ((ProjectileNetworkTransform)obj).CmdSetPositionAndRotationFromClient(reader.ReadVector3(), reader.ReadQuaternion()); + } + } + + public void CallCmdSetPositionAndRotationFromClient(Vector3 position, Quaternion rotation) + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdSetPositionAndRotationFromClient called on server."); + return; + } + if (base.isServer) + { + CmdSetPositionAndRotationFromClient(position, rotation); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdSetPositionAndRotationFromClient); + networkWriter.Write(GetComponent().netId); + networkWriter.Write(position); + networkWriter.Write(rotation); + SendCommandInternal(networkWriter, 0, "CmdSetPositionAndRotationFromClient"); + } + + static ProjectileNetworkTransform() + { + kCmdCmdSetPositionAndRotationFromClient = -895512346; + NetworkBehaviour.RegisterCommandDelegate(typeof(ProjectileNetworkTransform), kCmdCmdSetPositionAndRotationFromClient, InvokeCmdCmdSetPositionAndRotationFromClient); + NetworkCRC.RegisterBehaviour("ProjectileNetworkTransform", 0); + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(serverPosition); + writer.Write(serverRotation); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(serverPosition); + } + if ((base.syncVarDirtyBits & 2u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(serverRotation); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + serverPosition = reader.ReadVector3(); + serverRotation = reader.ReadQuaternion(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + OnSyncPosition(reader.ReadVector3()); + } + if (((uint)num & 2u) != 0) + { + OnSyncRotation(reader.ReadQuaternion()); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOverlapAttack.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOverlapAttack.cs new file mode 100644 index 0000000..93c36a0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOverlapAttack.cs @@ -0,0 +1,147 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileDamage))] +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(HitBoxGroup))] +public class ProjectileOverlapAttack : MonoBehaviour, IProjectileImpactBehavior +{ + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + public float damageCoefficient; + + public GameObject impactEffect; + + public Vector3 forceVector; + + public float overlapProcCoefficient = 1f; + + public int maximumOverlapTargets = 100; + + public UnityEvent onServerHit; + + private OverlapAttack attack; + + public float fireFrequency = 60f; + + [Tooltip("If non-negative, the attack clears its hit memory at the specified interval.")] + public float resetInterval = -1f; + + private float resetTimer; + + public bool requireDelayOnePhysicsFrame; + + [Header("Velocity Scaling")] + public bool ScaleWithVelocity; + + public Rigidbody ScaleVelocitySource; + + private Vector3[] HitboxOriginalScales; + + private Transform[] HitboxTransforms; + + public Vector3 ScaleWithVelocityAxis = new Vector3(0f, 0f, 1f); + + private float fireTimer; + + private void Start() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + attack = new OverlapAttack(); + attack.procChainMask = projectileController.procChainMask; + attack.procCoefficient = projectileController.procCoefficient * overlapProcCoefficient; + attack.attacker = projectileController.owner; + attack.inflictor = base.gameObject; + attack.teamIndex = projectileController.teamFilter.teamIndex; + attack.damage = damageCoefficient * projectileDamage.damage; + attack.forceVector = forceVector + projectileDamage.force * base.transform.forward; + attack.hitEffectPrefab = impactEffect; + attack.isCrit = projectileDamage.crit; + attack.damageColorIndex = projectileDamage.damageColorIndex; + attack.damageType = projectileDamage.damageType; + attack.procChainMask = projectileController.procChainMask; + attack.maximumOverlapTargets = maximumOverlapTargets; + attack.hitBoxGroup = GetComponent(); + int num = attack.hitBoxGroup.hitBoxes.Length; + HitboxOriginalScales = new Vector3[num]; + HitboxTransforms = new Transform[num]; + for (int i = 0; i < num; i++) + { + HitboxTransforms[i] = attack.hitBoxGroup.hitBoxes[i].transform; + HitboxOriginalScales[i] = HitboxTransforms[i].localScale; + } + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + } + + private void FixedUpdate() + { + MyFixedUpdate(Time.fixedDeltaTime); + } + + public void MyFixedUpdate(float deltaTime) + { + if (!((!(projectileController != null)) ? NetworkServer.active : projectileController.CanProcessCollisionEvents())) + { + return; + } + if (resetInterval >= 0f) + { + resetTimer -= deltaTime; + if (resetTimer <= 0f) + { + resetTimer = resetInterval; + ResetOverlapAttack(); + } + } + fireTimer -= deltaTime; + if (!(fireTimer <= 0f)) + { + return; + } + if (ScaleWithVelocity) + { + float num = 1f / fireFrequency - fireTimer; + if (num > 0f) + { + float num2 = num * ScaleVelocitySource.velocity.magnitude; + Vector3 rhs = ScaleWithVelocityAxis * num2; + int num3 = HitboxTransforms.Length; + for (int i = 0; i < num3; i++) + { + HitboxTransforms[i].localScale = Vector3.Max(HitboxOriginalScales[i], rhs); + } + } + } + fireTimer = 1f / fireFrequency; + attack.damage = damageCoefficient * projectileDamage.damage; + if (attack.Fire()) + { + onServerHit?.Invoke(); + } + } + + public void ResetOverlapAttack() + { + attack.damageType = projectileDamage.damageType; + attack.ResetIgnoredHealthComponents(); + } + + public void SetDamageCoefficient(float newDamageCoefficient) + { + damageCoefficient = newDamageCoefficient; + } + + public void AddToDamageCoefficient(float bonusDamageCoefficient) + { + damageCoefficient += bonusDamageCoefficient; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOverlapLimitHits.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOverlapLimitHits.cs new file mode 100644 index 0000000..00b6db0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOverlapLimitHits.cs @@ -0,0 +1,194 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileOverlapAttack))] +public class ProjectileOverlapLimitHits : NetworkBehaviour +{ + [Tooltip("How many hits this projectile can make before it will destroy itself.")] + [SerializeField] + public int hitLimit; + + [Tooltip("Announce in the console when the hit limit has been reached")] + [SerializeField] + private bool debugMessages; + + private ProjectileOverlapAttack projectileOverlapAttack; + + [Tooltip("Run when the projectile has one hit remaining.")] + [SerializeField] + public UnityEvent OnOneHitRemaining; + + private int hitCount; + + private static int kCmdCmdLastHit; + + private static int kRpcRpcLastHit; + + private void Awake() + { + projectileOverlapAttack = GetComponent(); + _ = projectileOverlapAttack == null; + } + + private void OnEnable() + { + projectileOverlapAttack.onServerHit.AddListener(CountOverlapHits); + } + + private void CountOverlapHits() + { + hitCount++; + if (hitCount == hitLimit - 1) + { + HandleNetworkedLastHit(); + } + if (hitCount >= hitLimit) + { + DestroyProjectile(); + } + } + + private void HandleNetworkedLastHit() + { + if (NetworkServer.active) + { + CallRpcLastHit(); + } + else + { + CallCmdLastHit(); + } + } + + [Command] + private void CmdLastHit() + { + CallRpcLastHit(); + } + + [ClientRpc] + private void RpcLastHit() + { + OnOneHitRemaining?.Invoke(); + } + + public bool IsLastHit() + { + return hitCount == hitLimit - 1; + } + + private void DestroyProjectile() + { + if (NetworkServer.active) + { + _ = debugMessages; + EffectManagerHelper component = GetComponent(); + if ((bool)component && component.OwningPool != null) + { + component.OwningPool.ReturnObject(component); + } + else + { + Object.Destroy(base.gameObject); + } + } + } + + private void OnDisable() + { + if (NetworkServer.active) + { + projectileOverlapAttack.onServerHit.RemoveListener(CountOverlapHits); + } + } + + private void UNetVersion() + { + } + + protected static void InvokeCmdCmdLastHit(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkServer.active) + { + Debug.LogError("Command CmdLastHit called on client."); + } + else + { + ((ProjectileOverlapLimitHits)obj).CmdLastHit(); + } + } + + public void CallCmdLastHit() + { + if (!NetworkClient.active) + { + Debug.LogError("Command function CmdLastHit called on server."); + return; + } + if (base.isServer) + { + CmdLastHit(); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)5); + networkWriter.WritePackedUInt32((uint)kCmdCmdLastHit); + networkWriter.Write(GetComponent().netId); + SendCommandInternal(networkWriter, 0, "CmdLastHit"); + } + + protected static void InvokeRpcRpcLastHit(NetworkBehaviour obj, NetworkReader reader) + { + if (!NetworkClient.active) + { + Debug.LogError("RPC RpcLastHit called on server."); + } + else + { + ((ProjectileOverlapLimitHits)obj).RpcLastHit(); + } + } + + public void CallRpcLastHit() + { + if (!NetworkServer.active) + { + Debug.LogError("RPC Function RpcLastHit called on client."); + return; + } + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.Write((short)0); + networkWriter.Write((short)2); + networkWriter.WritePackedUInt32((uint)kRpcRpcLastHit); + networkWriter.Write(GetComponent().netId); + SendRPCInternal(networkWriter, 0, "RpcLastHit"); + } + + static ProjectileOverlapLimitHits() + { + kCmdCmdLastHit = 809020640; + NetworkBehaviour.RegisterCommandDelegate(typeof(ProjectileOverlapLimitHits), kCmdCmdLastHit, InvokeCmdCmdLastHit); + kRpcRpcLastHit = -716657590; + NetworkBehaviour.RegisterRpcDelegate(typeof(ProjectileOverlapLimitHits), kRpcRpcLastHit, InvokeRpcRpcLastHit); + NetworkCRC.RegisterBehaviour("ProjectileOverlapLimitHits", 0); + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool result = default(bool); + return result; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOwnerOrbiter.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOwnerOrbiter.cs new file mode 100644 index 0000000..e0e710e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileOwnerOrbiter.cs @@ -0,0 +1,356 @@ +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[DisallowMultipleComponent] +public class ProjectileOwnerOrbiter : NetworkBehaviour +{ + [SyncVar] + [SerializeField] + private Vector3 offset; + + [SyncVar] + [SerializeField] + private float initialDegreesFromOwnerForward; + + [SerializeField] + [SyncVar] + private float degreesPerSecond; + + [SyncVar] + [SerializeField] + public float radius; + + [SyncVar] + [SerializeField] + private Vector3 planeNormal = Vector3.up; + + private Transform ownerTransform; + + private Rigidbody rigidBody; + + private bool resetOnAcquireOwner = true; + + [SyncVar] + private Vector3 initialRadialDirection; + + [SyncVar] + private float initialRunTime; + + public Vector3 Networkoffset + { + get + { + return offset; + } + [param: In] + set + { + SetSyncVar(value, ref offset, 1u); + } + } + + public float NetworkinitialDegreesFromOwnerForward + { + get + { + return initialDegreesFromOwnerForward; + } + [param: In] + set + { + SetSyncVar(value, ref initialDegreesFromOwnerForward, 2u); + } + } + + public float NetworkdegreesPerSecond + { + get + { + return degreesPerSecond; + } + [param: In] + set + { + SetSyncVar(value, ref degreesPerSecond, 4u); + } + } + + public float Networkradius + { + get + { + return radius; + } + [param: In] + set + { + SetSyncVar(value, ref radius, 8u); + } + } + + public Vector3 NetworkplaneNormal + { + get + { + return planeNormal; + } + [param: In] + set + { + SetSyncVar(value, ref planeNormal, 16u); + } + } + + public Vector3 NetworkinitialRadialDirection + { + get + { + return initialRadialDirection; + } + [param: In] + set + { + SetSyncVar(value, ref initialRadialDirection, 32u); + } + } + + public float NetworkinitialRunTime + { + get + { + return initialRunTime; + } + [param: In] + set + { + SetSyncVar(value, ref initialRunTime, 64u); + } + } + + public void Initialize(Vector3 planeNormal, float radius, float degreesPerSecond, float initialDegreesFromOwnerForward) + { + NetworkplaneNormal = planeNormal; + Networkradius = radius; + NetworkdegreesPerSecond = degreesPerSecond; + NetworkinitialDegreesFromOwnerForward = initialDegreesFromOwnerForward; + ResetState(); + } + + private void OnEnable() + { + rigidBody = GetComponent(); + ProjectileController component = GetComponent(); + if ((bool)component.owner) + { + AcquireOwner(component); + } + else + { + component.onInitialized += AcquireOwner; + } + } + + public void FixedUpdate() + { + UpdatePosition(doSnap: false); + } + + private void ResetState() + { + NetworkinitialRunTime = Time.fixedTime; + planeNormal.Normalize(); + if ((bool)ownerTransform) + { + NetworkinitialRadialDirection = Quaternion.AngleAxis(initialDegreesFromOwnerForward, planeNormal) * ownerTransform.forward; + resetOnAcquireOwner = false; + } + UpdatePosition(doSnap: true); + } + + private void UpdatePosition(bool doSnap) + { + if ((bool)ownerTransform) + { + float angle = (Time.fixedTime - initialRunTime) * degreesPerSecond; + Vector3 position = ownerTransform.position + offset + Quaternion.AngleAxis(angle, planeNormal) * initialRadialDirection * radius; + if (!rigidBody || doSnap) + { + base.transform.position = position; + } + else if ((bool)rigidBody) + { + rigidBody.MovePosition(position); + } + } + } + + public void SetInitialDegreesFromOwnerForward(float degrees) + { + NetworkinitialDegreesFromOwnerForward = degrees; + if ((bool)ownerTransform) + { + NetworkinitialRadialDirection = Quaternion.AngleAxis(initialDegreesFromOwnerForward, planeNormal) * ownerTransform.forward; + } + } + + public float GetInitialRunTime() + { + return initialRunTime; + } + + public void SetInitialRunTime(float _time) + { + NetworkinitialRunTime = Mathf.Max(_time, 0f); + } + + private void AcquireOwner(ProjectileController controller) + { + ownerTransform = controller.owner.transform; + controller.onInitialized -= AcquireOwner; + if (resetOnAcquireOwner) + { + resetOnAcquireOwner = false; + ResetState(); + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(offset); + writer.Write(initialDegreesFromOwnerForward); + writer.Write(degreesPerSecond); + writer.Write(radius); + writer.Write(planeNormal); + writer.Write(initialRadialDirection); + writer.Write(initialRunTime); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(offset); + } + if ((base.syncVarDirtyBits & 2u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(initialDegreesFromOwnerForward); + } + if ((base.syncVarDirtyBits & 4u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(degreesPerSecond); + } + if ((base.syncVarDirtyBits & 8u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(radius); + } + if ((base.syncVarDirtyBits & 0x10u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(planeNormal); + } + if ((base.syncVarDirtyBits & 0x20u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(initialRadialDirection); + } + if ((base.syncVarDirtyBits & 0x40u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(initialRunTime); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + offset = reader.ReadVector3(); + initialDegreesFromOwnerForward = reader.ReadSingle(); + degreesPerSecond = reader.ReadSingle(); + radius = reader.ReadSingle(); + planeNormal = reader.ReadVector3(); + initialRadialDirection = reader.ReadVector3(); + initialRunTime = reader.ReadSingle(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + offset = reader.ReadVector3(); + } + if (((uint)num & 2u) != 0) + { + initialDegreesFromOwnerForward = reader.ReadSingle(); + } + if (((uint)num & 4u) != 0) + { + degreesPerSecond = reader.ReadSingle(); + } + if (((uint)num & 8u) != 0) + { + radius = reader.ReadSingle(); + } + if (((uint)num & 0x10u) != 0) + { + planeNormal = reader.ReadVector3(); + } + if (((uint)num & 0x20u) != 0) + { + initialRadialDirection = reader.ReadVector3(); + } + if (((uint)num & 0x40u) != 0) + { + initialRunTime = reader.ReadSingle(); + } + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileParentTether.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileParentTether.cs new file mode 100644 index 0000000..def3637 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileParentTether.cs @@ -0,0 +1,142 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileDamage))] +[RequireComponent(typeof(ProjectileController))] +public class ProjectileParentTether : MonoBehaviour +{ + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private TeamIndex myTeamIndex; + + public float attackInterval = 1f; + + public float maxTetherRange = 20f; + + public float procCoefficient = 0.1f; + + public float damageCoefficient = 1f; + + public float raycastRadius; + + public float lifetime; + + public GameObject impactEffect; + + public GameObject tetherEffectPrefab; + + public ProjectileStickOnImpact stickOnImpact; + + private GameObject tetherEffectInstance; + + private GameObject tetherEffectInstanceEnd; + + private float attackTimer; + + private float lifetimeStopwatch; + + private void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + attackTimer = 0f; + UpdateTetherGraphic(); + } + + private void UpdateTetherGraphic() + { + if (ShouldIFire()) + { + if ((bool)tetherEffectPrefab && !tetherEffectInstance) + { + tetherEffectInstance = Object.Instantiate(tetherEffectPrefab, base.transform.position, base.transform.rotation); + tetherEffectInstance.transform.parent = base.transform; + ChildLocator component = tetherEffectInstance.GetComponent(); + tetherEffectInstanceEnd = component.FindChild("LaserEnd").gameObject; + } + if ((bool)tetherEffectInstance) + { + Ray aimRay = GetAimRay(); + tetherEffectInstance.transform.rotation = Util.QuaternionSafeLookRotation(aimRay.direction); + tetherEffectInstanceEnd.transform.position = aimRay.origin + aimRay.direction * GetRayDistance(); + } + } + } + + private float GetRayDistance() + { + if ((bool)projectileController.owner) + { + return (projectileController.owner.transform.position - base.transform.position).magnitude; + } + return 0f; + } + + private Ray GetAimRay() + { + Ray result = default(Ray); + result.origin = base.transform.position; + result.direction = projectileController.owner.transform.position - result.origin; + return result; + } + + private bool ShouldIFire() + { + if ((bool)stickOnImpact) + { + return stickOnImpact.stuck; + } + return true; + } + + private void Update() + { + UpdateTetherGraphic(); + } + + private void FixedUpdate() + { + if (ShouldIFire()) + { + lifetimeStopwatch += Time.fixedDeltaTime; + } + if (lifetimeStopwatch > lifetime) + { + Object.Destroy(base.gameObject); + } + if (!projectileController.owner.transform || !ShouldIFire()) + { + return; + } + myTeamIndex = (projectileController.teamFilter ? projectileController.teamFilter.teamIndex : TeamIndex.Neutral); + attackTimer -= Time.fixedDeltaTime; + if (attackTimer <= 0f) + { + Ray aimRay = GetAimRay(); + attackTimer = attackInterval; + if (aimRay.direction.magnitude < maxTetherRange && NetworkServer.active) + { + BulletAttack bulletAttack = new BulletAttack(); + bulletAttack.owner = projectileController.owner; + bulletAttack.origin = aimRay.origin; + bulletAttack.aimVector = aimRay.direction; + bulletAttack.minSpread = 0f; + bulletAttack.damage = damageCoefficient * projectileDamage.damage; + bulletAttack.force = 0f; + bulletAttack.hitEffectPrefab = impactEffect; + bulletAttack.isCrit = projectileDamage.crit; + bulletAttack.radius = raycastRadius; + bulletAttack.falloffModel = BulletAttack.FalloffModel.None; + bulletAttack.stopperMask = 0; + bulletAttack.hitMask = LayerIndex.entityPrecise.mask; + bulletAttack.procCoefficient = procCoefficient; + bulletAttack.maxDistance = GetRayDistance(); + bulletAttack.Fire(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileProximityBeamController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileProximityBeamController.cs new file mode 100644 index 0000000..656e3df --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileProximityBeamController.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using System.Linq; +using RoR2.Orbs; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +[RequireComponent(typeof(ProjectileDamage))] +public class ProjectileProximityBeamController : MonoBehaviour +{ + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private List previousTargets; + + private TeamFilter teamFilter; + + public int attackFireCount = 1; + + public float attackInterval = 1f; + + public float listClearInterval = 3f; + + public float attackRange = 20f; + + [Range(0f, 180f)] + public float minAngleFilter; + + [Range(0f, 180f)] + public float maxAngleFilter = 180f; + + public float procCoefficient = 0.1f; + + public float damageCoefficient = 1f; + + public int bounces; + + public bool inheritDamageType; + + public LightningOrb.LightningType lightningType = LightningOrb.LightningType.BFG; + + private float attackTimer; + + private float listClearTimer; + + private BullseyeSearch search; + + private TeamIndex myTeamIndex + { + get + { + if (!teamFilter) + { + return TeamIndex.Neutral; + } + return teamFilter.teamIndex; + } + } + + private void Awake() + { + if (NetworkServer.active) + { + projectileController = GetComponent(); + teamFilter = projectileController.teamFilter; + projectileDamage = GetComponent(); + attackTimer = 0f; + previousTargets = new List(); + search = new BullseyeSearch(); + } + else + { + base.enabled = false; + } + } + + private void ClearList() + { + previousTargets.Clear(); + } + + private void FixedUpdate() + { + if (NetworkServer.active) + { + UpdateServer(); + } + else + { + base.enabled = false; + } + } + + private void UpdateServer() + { + listClearTimer -= Time.fixedDeltaTime; + if (listClearTimer <= 0f) + { + ClearList(); + listClearTimer = listClearInterval; + } + attackTimer -= Time.fixedDeltaTime; + if (!(attackTimer <= 0f)) + { + return; + } + attackTimer += attackInterval; + Vector3 position = base.transform.position; + Vector3 forward = base.transform.forward; + for (int i = 0; i < attackFireCount; i++) + { + HurtBox hurtBox = FindNextTarget(position, forward); + if ((bool)hurtBox) + { + previousTargets.Add(hurtBox.healthComponent); + LightningOrb lightningOrb = new LightningOrb(); + lightningOrb.bouncedObjects = new List(); + lightningOrb.attacker = projectileController.owner; + lightningOrb.inflictor = base.gameObject; + lightningOrb.teamIndex = myTeamIndex; + lightningOrb.damageValue = projectileDamage.damage * damageCoefficient; + lightningOrb.isCrit = projectileDamage.crit; + lightningOrb.origin = position; + lightningOrb.bouncesRemaining = bounces; + lightningOrb.lightningType = lightningType; + lightningOrb.procCoefficient = procCoefficient; + lightningOrb.target = hurtBox; + lightningOrb.damageColorIndex = projectileDamage.damageColorIndex; + if (inheritDamageType) + { + lightningOrb.damageType = projectileDamage.damageType; + } + OrbManager.instance.AddOrb(lightningOrb); + } + } + } + + public HurtBox FindNextTarget(Vector3 position, Vector3 forward) + { + search.searchOrigin = position; + search.searchDirection = forward; + search.sortMode = BullseyeSearch.SortMode.Distance; + search.teamMaskFilter = TeamMask.allButNeutral; + search.teamMaskFilter.RemoveTeam(myTeamIndex); + search.filterByLoS = false; + search.minAngleFilter = minAngleFilter; + search.maxAngleFilter = maxAngleFilter; + search.maxDistanceFilter = attackRange; + search.RefreshCandidates(); + return search.GetResults().FirstOrDefault((HurtBox hurtBox) => !previousTargets.Contains(hurtBox.healthComponent)); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSimple.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSimple.cs new file mode 100644 index 0000000..b17abb9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSimple.cs @@ -0,0 +1,118 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.Serialization; + +namespace RoR2.Projectile; + +public class ProjectileSimple : MonoBehaviour +{ + [Header("Lifetime")] + public float lifetime = 5f; + + public GameObject lifetimeExpiredEffect; + + [FormerlySerializedAs("velocity")] + [Header("Velocity")] + public float desiredForwardSpeed; + + public bool updateAfterFiring; + + public bool enableVelocityOverLifetime; + + public AnimationCurve velocityOverLifetime; + + [Header("Oscillation")] + public bool oscillate; + + public float oscillateMagnitude = 20f; + + public float oscillateSpeed; + + private float deltaHeight; + + private float oscillationStopwatch; + + private float stopwatch; + + private Rigidbody rigidbody; + + private new Transform transform; + + [Obsolete("Use 'desiredForwardSpeed' instead.", false)] + public float velocity + { + get + { + return desiredForwardSpeed; + } + set + { + desiredForwardSpeed = value; + } + } + + protected void Awake() + { + transform = base.transform; + rigidbody = GetComponent(); + } + + protected void OnEnable() + { + SetForwardSpeed(desiredForwardSpeed); + } + + protected void Start() + { + SetForwardSpeed(desiredForwardSpeed); + } + + protected void OnDisable() + { + SetForwardSpeed(0f); + } + + protected void FixedUpdate() + { + if (oscillate) + { + deltaHeight = Mathf.Sin(oscillationStopwatch * oscillateSpeed); + } + if (updateAfterFiring || enableVelocityOverLifetime) + { + SetForwardSpeed(desiredForwardSpeed); + } + oscillationStopwatch += Time.deltaTime; + stopwatch += Time.deltaTime; + if (NetworkServer.active && stopwatch > lifetime) + { + UnityEngine.Object.Destroy(base.gameObject); + if ((bool)lifetimeExpiredEffect && NetworkServer.active) + { + EffectManager.SimpleEffect(lifetimeExpiredEffect, transform.position, transform.rotation, transmit: true); + } + } + } + + public void SetLifetime(float newLifetime) + { + lifetime = newLifetime; + stopwatch = 0f; + } + + protected void SetForwardSpeed(float speed) + { + if ((bool)rigidbody) + { + if (enableVelocityOverLifetime) + { + rigidbody.velocity = speed * velocityOverLifetime.Evaluate(stopwatch / lifetime) * transform.forward; + } + else + { + rigidbody.velocity = transform.forward * speed + transform.right * (deltaHeight * oscillateMagnitude); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSingleTargetImpact.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSingleTargetImpact.cs new file mode 100644 index 0000000..89d9407 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSingleTargetImpact.cs @@ -0,0 +1,100 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileSingleTargetImpact : MonoBehaviour, IProjectileImpactBehavior +{ + private ProjectileController projectileController; + + private ProjectileDamage projectileDamage; + + private bool alive = true; + + public bool destroyWhenNotAlive = true; + + public bool destroyOnWorld; + + public GameObject impactEffect; + + public string hitSoundString; + + public string enemyHitSoundString; + + private void Awake() + { + projectileController = GetComponent(); + projectileDamage = GetComponent(); + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (!alive) + { + return; + } + Collider collider = impactInfo.collider; + if ((bool)collider) + { + DamageInfo damageInfo = new DamageInfo(); + if ((bool)projectileDamage) + { + damageInfo.damage = projectileDamage.damage; + damageInfo.crit = projectileDamage.crit; + damageInfo.attacker = projectileController.owner; + damageInfo.inflictor = base.gameObject; + damageInfo.position = impactInfo.estimatedPointOfImpact; + damageInfo.force = projectileDamage.force * base.transform.forward; + damageInfo.procChainMask = projectileController.procChainMask; + damageInfo.procCoefficient = projectileController.procCoefficient; + damageInfo.damageColorIndex = projectileDamage.damageColorIndex; + damageInfo.damageType = projectileDamage.damageType; + } + HurtBox component = collider.GetComponent(); + if ((bool)component) + { + HealthComponent healthComponent = component.healthComponent; + if ((bool)healthComponent) + { + if (healthComponent.gameObject == projectileController.owner) + { + return; + } + if (FriendlyFireManager.ShouldDirectHitProceed(healthComponent, projectileController.teamFilter.teamIndex)) + { + Util.PlaySound(enemyHitSoundString, base.gameObject); + if (NetworkServer.active) + { + damageInfo.ModifyDamageInfo(component.damageModifier); + healthComponent.TakeDamage(damageInfo); + GlobalEventManager.instance.OnHitEnemy(damageInfo, component.healthComponent.gameObject); + } + } + alive = false; + } + } + else if (destroyOnWorld) + { + alive = false; + } + damageInfo.position = base.transform.position; + if (NetworkServer.active) + { + GlobalEventManager.instance.OnHitAll(damageInfo, collider.gameObject); + } + } + if (!alive) + { + if (NetworkServer.active && (bool)impactEffect) + { + EffectManager.SimpleImpactEffect(impactEffect, impactInfo.estimatedPointOfImpact, -base.transform.forward, !projectileController.isPrediction); + } + Util.PlaySound(hitSoundString, base.gameObject); + if (destroyWhenNotAlive) + { + Object.Destroy(base.gameObject); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSpawnMaster.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSpawnMaster.cs new file mode 100644 index 0000000..6e26cd1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSpawnMaster.cs @@ -0,0 +1,83 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class ProjectileSpawnMaster : MonoBehaviour, IProjectileImpactBehavior +{ + [SerializeField] + private float maxLifetime = 10f; + + [SerializeField] + private CharacterSpawnCard spawnCard; + + [SerializeField] + public DeployableSlot deployableSlot = DeployableSlot.None; + + private float stopwatch; + + private bool isAlive = true; + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (isAlive) + { + SpawnMaster(); + isAlive = false; + } + } + + protected void FixedUpdate() + { + stopwatch += Time.fixedDeltaTime; + if (NetworkServer.active && (!isAlive || stopwatch > maxLifetime)) + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + public void SpawnMaster() + { + ProjectileController component = GetComponent(); + if (!component || !component.owner) + { + return; + } + CharacterBody component2 = component.owner.GetComponent(); + if (!component2 || !component2.master || !spawnCard) + { + return; + } + CharacterMaster characterMaster = component2.master; + if (!characterMaster || (deployableSlot != DeployableSlot.None && characterMaster.IsDeployableLimited(deployableSlot))) + { + return; + } + Transform spawnOnTarget = base.transform; + DirectorPlacementRule directorPlacementRule = new DirectorPlacementRule + { + spawnOnTarget = spawnOnTarget, + placementMode = DirectorPlacementRule.PlacementMode.Direct + }; + DirectorCore.GetMonsterSpawnDistance(DirectorCore.MonsterSpawnDistance.Close, out directorPlacementRule.minDistance, out directorPlacementRule.maxDistance); + DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(spawnCard, directorPlacementRule, new Xoroshiro128Plus(Run.instance.seed + (ulong)Run.instance.fixedTime)); + directorSpawnRequest.teamIndexOverride = characterMaster.teamIndex; + directorSpawnRequest.ignoreTeamMemberLimit = false; + directorSpawnRequest.summonerBodyObject = component.owner; + if (deployableSlot != DeployableSlot.None) + { + directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult result) + { + if (result.success && (bool)result.spawnedInstance) + { + result.spawnedInstance.GetComponent(); + Deployable deployable = result.spawnedInstance.AddComponent(); + characterMaster.AddDeployable(deployable, deployableSlot); + } + }); + } + DirectorCore.instance.TrySpawnObject(directorSpawnRequest); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSphereTargetFinder.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSphereTargetFinder.cs new file mode 100644 index 0000000..36465d1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSphereTargetFinder.cs @@ -0,0 +1,163 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; +using UnityEngine.Serialization; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileTargetComponent))] +[RequireComponent(typeof(TeamFilter))] +public class ProjectileSphereTargetFinder : MonoBehaviour +{ + [Tooltip("How far ahead the projectile should look to find a target.")] + public float lookRange; + + [Tooltip("How long before searching for a target.")] + public float targetSearchInterval = 0.5f; + + [Tooltip("Will not search for new targets once it has one.")] + public bool onlySearchIfNoTarget; + + [Tooltip("Allows the target to be lost if it's outside the acceptable range.")] + public bool allowTargetLoss; + + [Tooltip("If set, targets can only be found when there is a free line of sight.")] + public bool testLoS; + + [Tooltip("Whether or not airborne characters should be ignored.")] + public bool ignoreAir; + + [Tooltip("The difference in altitude at which a result will be ignored.")] + [FormerlySerializedAs("altitudeTolerance")] + public float flierAltitudeTolerance = float.PositiveInfinity; + + public UnityEvent onNewTargetFound; + + public UnityEvent onTargetLost; + + private new Transform transform; + + private TeamFilter teamFilter; + + private ProjectileTargetComponent targetComponent; + + private float searchTimer; + + private SphereSearch sphereSearch; + + private bool hasTarget; + + private bool hadTargetLastUpdate; + + private HurtBox lastFoundHurtBox; + + private Transform lastFoundTransform; + + private static readonly List foundHurtBoxes = new List(); + + private void Start() + { + if (!NetworkServer.active) + { + base.enabled = false; + return; + } + transform = base.transform; + teamFilter = GetComponent(); + targetComponent = GetComponent(); + sphereSearch = new SphereSearch(); + searchTimer = 0f; + } + + private void FixedUpdate() + { + searchTimer -= Time.fixedDeltaTime; + if (!(searchTimer <= 0f)) + { + return; + } + searchTimer += targetSearchInterval; + if (allowTargetLoss && (object)targetComponent.target != null && (object)lastFoundTransform == targetComponent.target && !PassesFilters(lastFoundHurtBox)) + { + SetTarget(null); + } + if (!onlySearchIfNoTarget || targetComponent.target == null) + { + SearchForTarget(); + } + hasTarget = targetComponent.target != null; + if (hadTargetLastUpdate != hasTarget) + { + if (hasTarget) + { + onNewTargetFound?.Invoke(); + } + else + { + onTargetLost?.Invoke(); + } + } + hadTargetLastUpdate = hasTarget; + } + + private bool PassesFilters(HurtBox result) + { + CharacterBody body = result.healthComponent.body; + if (!body || (ignoreAir && body.isFlying)) + { + return false; + } + if (body.isFlying && !float.IsInfinity(flierAltitudeTolerance) && flierAltitudeTolerance < Mathf.Abs(result.transform.position.y - transform.position.y)) + { + return false; + } + return true; + } + + private void SearchForTarget() + { + sphereSearch.origin = transform.position; + sphereSearch.radius = lookRange; + sphereSearch.mask = LayerIndex.entityPrecise.mask; + sphereSearch.queryTriggerInteraction = QueryTriggerInteraction.UseGlobal; + sphereSearch.RefreshCandidates(); + sphereSearch.FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(teamFilter.teamIndex)); + sphereSearch.OrderCandidatesByDistance(); + sphereSearch.FilterCandidatesByDistinctHurtBoxEntities(); + sphereSearch.GetHurtBoxes(foundHurtBoxes); + HurtBox target = null; + if (foundHurtBoxes.Count > 0) + { + int i = 0; + for (int count = foundHurtBoxes.Count; i < count; i++) + { + if (PassesFilters(foundHurtBoxes[i])) + { + target = foundHurtBoxes[i]; + break; + } + } + foundHurtBoxes.Clear(); + } + SetTarget(target); + } + + private void SetTarget(HurtBox hurtBox) + { + lastFoundHurtBox = hurtBox; + lastFoundTransform = hurtBox?.transform; + targetComponent.target = lastFoundTransform; + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.yellow; + Vector3 position = base.transform.position; + Gizmos.DrawWireSphere(position, lookRange); + if (!float.IsInfinity(flierAltitudeTolerance)) + { + Gizmos.DrawWireCube(position, new Vector3(lookRange * 2f, flierAltitudeTolerance * 2f, lookRange * 2f)); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSteerTowardTarget.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSteerTowardTarget.cs new file mode 100644 index 0000000..945e778 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileSteerTowardTarget.cs @@ -0,0 +1,46 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileTargetComponent))] +public class ProjectileSteerTowardTarget : MonoBehaviour +{ + [Tooltip("Constrains rotation to the Y axis only.")] + public bool yAxisOnly; + + [Tooltip("How fast to rotate in degrees per second. Rotation is linear.")] + public float rotationSpeed; + + private new Transform transform; + + private ProjectileTargetComponent targetComponent; + + private void Start() + { + if (!NetworkServer.active) + { + base.enabled = false; + return; + } + transform = base.transform; + targetComponent = GetComponent(); + } + + private void FixedUpdate() + { + if ((bool)targetComponent.target) + { + Vector3 vector = targetComponent.target.transform.position - transform.position; + if (yAxisOnly) + { + vector.y = 0f; + } + if (vector != Vector3.zero) + { + transform.forward = Vector3.RotateTowards(transform.forward, vector, rotationSpeed * (MathF.PI / 180f) * Time.fixedDeltaTime, 0f); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileStickOnImpact.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileStickOnImpact.cs new file mode 100644 index 0000000..fc2e668 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileStickOnImpact.cs @@ -0,0 +1,432 @@ +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(Rigidbody))] +[RequireComponent(typeof(ProjectileController))] +[DefaultExecutionOrder(-1)] +[RequireComponent(typeof(ProjectileNetworkTransform))] +public class ProjectileStickOnImpact : NetworkBehaviour, IProjectileImpactBehavior +{ + public string stickSoundString; + + public ParticleSystem[] stickParticleSystem; + + public bool ignoreCharacters; + + public bool ignoreWorld; + + public bool alignNormals = true; + + public UnityEvent stickEvent; + + private ProjectileController projectileController; + + private Rigidbody rigidbody; + + private bool wasEverEnabled; + + private GameObject _victim; + + [SyncVar] + private GameObject syncVictim; + + [SyncVar] + private sbyte hitHurtboxIndex = -1; + + [SyncVar] + private Vector3 localPosition; + + [SyncVar] + private Quaternion localRotation; + + [SyncVar] + private bool runStickEvent; + + private bool alreadyRanStickEvent; + + private NetworkInstanceId ___syncVictimNetId; + + public Transform stuckTransform { get; private set; } + + public CharacterBody stuckBody { get; private set; } + + public GameObject victim + { + get + { + return _victim; + } + private set + { + _victim = value; + NetworksyncVictim = value; + } + } + + public bool stuck => hitHurtboxIndex != -1; + + public GameObject NetworksyncVictim + { + get + { + return syncVictim; + } + [param: In] + set + { + SetSyncVarGameObject(value, ref syncVictim, 1u, ref ___syncVictimNetId); + } + } + + public sbyte NetworkhitHurtboxIndex + { + get + { + return hitHurtboxIndex; + } + [param: In] + set + { + SetSyncVar(value, ref hitHurtboxIndex, 2u); + } + } + + public Vector3 NetworklocalPosition + { + get + { + return localPosition; + } + [param: In] + set + { + SetSyncVar(value, ref localPosition, 4u); + } + } + + public Quaternion NetworklocalRotation + { + get + { + return localRotation; + } + [param: In] + set + { + SetSyncVar(value, ref localRotation, 8u); + } + } + + public bool NetworkrunStickEvent + { + get + { + return runStickEvent; + } + [param: In] + set + { + SetSyncVar(value, ref runStickEvent, 16u); + } + } + + private void Awake() + { + projectileController = GetComponent(); + rigidbody = GetComponent(); + } + + private void OnEnable() + { + if (wasEverEnabled) + { + Collider component = GetComponent(); + component.enabled = false; + component.enabled = true; + } + wasEverEnabled = true; + } + + private void OnDisable() + { + if (NetworkServer.active) + { + Detach(); + } + } + + [Server] + public void Detach() + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.Projectile.ProjectileStickOnImpact::Detach()' called on client"); + return; + } + victim = null; + stuckTransform = null; + NetworkhitHurtboxIndex = -1; + UpdateSticking(); + } + + public void OnProjectileImpact(ProjectileImpactInfo impactInfo) + { + if (base.enabled) + { + TrySticking(impactInfo.collider, impactInfo.estimatedImpactNormal); + } + } + + private bool TrySticking(Collider hitCollider, Vector3 impactNormal) + { + if ((bool)victim) + { + return false; + } + GameObject gameObject = null; + sbyte networkhitHurtboxIndex = -1; + HurtBox component = hitCollider.GetComponent(); + if ((bool)component) + { + HealthComponent healthComponent = component.healthComponent; + if ((bool)healthComponent) + { + gameObject = healthComponent.gameObject; + } + networkhitHurtboxIndex = (sbyte)component.indexInGroup; + } + if (!gameObject && !ignoreWorld) + { + gameObject = hitCollider.gameObject; + networkhitHurtboxIndex = -2; + } + if (gameObject == projectileController.owner || (ignoreCharacters && (bool)component)) + { + gameObject = null; + networkhitHurtboxIndex = -1; + } + if ((bool)gameObject) + { + NetworkrunStickEvent = true; + ParticleSystem[] array = stickParticleSystem; + for (int i = 0; i < array.Length; i++) + { + array[i].Play(); + } + if (stickSoundString.Length > 0) + { + Util.PlaySound(stickSoundString, base.gameObject); + } + if (alignNormals && impactNormal != Vector3.zero) + { + base.transform.rotation = Util.QuaternionSafeLookRotation(impactNormal, base.transform.up); + } + Transform transform = hitCollider.transform; + NetworklocalPosition = transform.InverseTransformPoint(base.transform.position); + NetworklocalRotation = Quaternion.Inverse(transform.rotation) * base.transform.rotation; + victim = gameObject; + NetworkhitHurtboxIndex = networkhitHurtboxIndex; + return true; + } + return false; + } + + private void FixedUpdate() + { + MyFixedUpdate(Time.deltaTime); + } + + private void UpdateSticking() + { + bool flag = stuckTransform; + if (flag) + { + base.transform.SetPositionAndRotation(stuckTransform.TransformPoint(localPosition), alignNormals ? (stuckTransform.rotation * localRotation) : base.transform.rotation); + } + else + { + GameObject gameObject = (NetworkServer.active ? victim : syncVictim); + if ((bool)gameObject) + { + stuckTransform = gameObject.transform; + flag = true; + if (hitHurtboxIndex >= 0) + { + stuckBody = stuckTransform.GetComponent(); + if ((bool)stuckBody && hitHurtboxIndex < stuckBody.hurtBoxGroup.hurtBoxes.Length && stuckBody.hurtBoxGroup.hurtBoxes[hitHurtboxIndex] != null) + { + stuckTransform = stuckBody.hurtBoxGroup.hurtBoxes[hitHurtboxIndex].transform; + } + ModelLocator component = syncVictim.GetComponent(); + if ((bool)component) + { + Transform modelTransform = component.modelTransform; + if ((bool)modelTransform) + { + HurtBoxGroup component2 = modelTransform.GetComponent(); + if ((bool)component2) + { + HurtBox hurtBox = component2.hurtBoxes[hitHurtboxIndex]; + if ((bool)hurtBox) + { + stuckTransform = hurtBox.transform; + } + } + } + } + } + } + else if (hitHurtboxIndex == -2 && !NetworkServer.active) + { + flag = true; + } + } + if (!NetworkServer.active) + { + return; + } + if (rigidbody.isKinematic != flag) + { + if (flag) + { + rigidbody.detectCollisions = false; + rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete; + rigidbody.isKinematic = true; + } + else + { + rigidbody.detectCollisions = true; + rigidbody.isKinematic = false; + rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; + } + } + if (!flag) + { + NetworkhitHurtboxIndex = -1; + } + } + + public void MyFixedUpdate(float deltaTime) + { + UpdateSticking(); + if (!alreadyRanStickEvent && runStickEvent) + { + stickEvent.Invoke(); + alreadyRanStickEvent = true; + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + if (forceAll) + { + writer.Write(syncVictim); + writer.WritePackedUInt32((uint)hitHurtboxIndex); + writer.Write(localPosition); + writer.Write(localRotation); + writer.Write(runStickEvent); + return true; + } + bool flag = false; + if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(syncVictim); + } + if ((base.syncVarDirtyBits & 2u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.WritePackedUInt32((uint)hitHurtboxIndex); + } + if ((base.syncVarDirtyBits & 4u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(localPosition); + } + if ((base.syncVarDirtyBits & 8u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(localRotation); + } + if ((base.syncVarDirtyBits & 0x10u) != 0) + { + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + flag = true; + } + writer.Write(runStickEvent); + } + if (!flag) + { + writer.WritePackedUInt32(base.syncVarDirtyBits); + } + return flag; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + { + ___syncVictimNetId = reader.ReadNetworkId(); + hitHurtboxIndex = (sbyte)reader.ReadPackedUInt32(); + localPosition = reader.ReadVector3(); + localRotation = reader.ReadQuaternion(); + runStickEvent = reader.ReadBoolean(); + return; + } + int num = (int)reader.ReadPackedUInt32(); + if (((uint)num & (true ? 1u : 0u)) != 0) + { + syncVictim = reader.ReadGameObject(); + } + if (((uint)num & 2u) != 0) + { + hitHurtboxIndex = (sbyte)reader.ReadPackedUInt32(); + } + if (((uint)num & 4u) != 0) + { + localPosition = reader.ReadVector3(); + } + if (((uint)num & 8u) != 0) + { + localRotation = reader.ReadQuaternion(); + } + if (((uint)num & 0x10u) != 0) + { + runStickEvent = reader.ReadBoolean(); + } + } + + public override void PreStartClient() + { + if (!___syncVictimNetId.IsEmpty()) + { + NetworksyncVictim = ClientScene.FindLocalObject(___syncVictimNetId); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileTargetComponent.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileTargetComponent.cs new file mode 100644 index 0000000..a915c1b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/ProjectileTargetComponent.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace RoR2.Projectile; + +public class ProjectileTargetComponent : MonoBehaviour +{ + public Transform target { get; set; } + + private void FixedUpdate() + { + if ((bool)target && !target.gameObject.activeSelf) + { + target = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/SlowDownProjectiles.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/SlowDownProjectiles.cs new file mode 100644 index 0000000..2cd62ce --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/SlowDownProjectiles.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(Collider))] +public class SlowDownProjectiles : MonoBehaviour +{ + private struct SlowDownProjectileInfo + { + public Rigidbody rb; + + public Vector3 previousVelocity; + } + + public TeamFilter teamFilter; + + public float slowDownCoefficient; + + private List slowDownProjectileInfos; + + private void Start() + { + slowDownProjectileInfos = new List(); + } + + private void Update() + { + } + + private void OnTriggerEnter(Collider other) + { + TeamFilter component = other.GetComponent(); + Rigidbody component2 = other.GetComponent(); + if ((bool)component2 && component.teamIndex != teamFilter.teamIndex) + { + slowDownProjectileInfos.Add(new SlowDownProjectileInfo + { + rb = component2, + previousVelocity = component2.velocity + }); + } + } + + private void OnTriggerExit(Collider other) + { + TeamFilter component = other.GetComponent(); + Rigidbody component2 = other.GetComponent(); + if ((bool)component2 && component.teamIndex != teamFilter.teamIndex) + { + RemoveFromSlowDownProjectileInfos(component2); + } + } + + private void RemoveFromSlowDownProjectileInfos(Rigidbody rb) + { + for (int i = 0; i < slowDownProjectileInfos.Count; i++) + { + if (slowDownProjectileInfos[i].rb == rb) + { + slowDownProjectileInfos.RemoveAt(i); + break; + } + } + } + + private void FixedUpdate() + { + for (int i = 0; i < slowDownProjectileInfos.Count; i++) + { + SlowDownProjectileInfo value = slowDownProjectileInfos[i]; + Rigidbody rb = value.rb; + Vector3 previousVelocity = value.previousVelocity; + if ((bool)rb) + { + rb.MovePosition(rb.position - Vector3.Lerp(previousVelocity, Vector3.zero, slowDownCoefficient) * Time.fixedDeltaTime); + value.previousVelocity = rb.velocity; + slowDownProjectileInfos[i] = value; + } + else + { + RemoveFromSlowDownProjectileInfos(rb); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/SoulSearchController.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/SoulSearchController.cs new file mode 100644 index 0000000..adf8b3e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/SoulSearchController.cs @@ -0,0 +1,88 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileTargetComponent))] +[RequireComponent(typeof(Rigidbody))] +public class SoulSearchController : MonoBehaviour +{ + private new Transform transform; + + private Rigidbody rigidbody; + + private TeamFilter teamFilter; + + private HurtBox trackingTarget; + + private ProjectileController projectileController; + + public float maxVelocity; + + public float rollVelocity; + + public float acceleration; + + public float delayTimer; + + public float giveupTimer = 8f; + + public float deathTimer = 10f; + + private float timer; + + private QuaternionPID torquePID; + + public float turbulence; + + public float maxSeekDistance = 40f; + + private void Awake() + { + if (!NetworkServer.active) + { + base.enabled = false; + return; + } + transform = base.transform; + rigidbody = GetComponent(); + torquePID = GetComponent(); + teamFilter = GetComponent(); + projectileController = GetComponent(); + } + + private void FixedUpdate() + { + timer += Time.fixedDeltaTime; + if (!trackingTarget) + { + trackingTarget = projectileController.owner.GetComponent().GetTrackingTarget(); + } + else + { + HealthComponent component = trackingTarget.GetComponent(); + if ((bool)component && !component.alive) + { + Object.Destroy(base.gameObject); + } + } + if (timer > deathTimer) + { + Object.Destroy(base.gameObject); + } + rigidbody.velocity = transform.forward * maxVelocity; + if ((bool)trackingTarget && timer >= delayTimer) + { + rigidbody.velocity = transform.forward * (maxVelocity + timer * acceleration); + Vector3 vector = trackingTarget.transform.position + Random.insideUnitSphere * turbulence - transform.position; + if (vector != Vector3.zero) + { + Quaternion rotation = transform.rotation; + Quaternion targetQuat = Util.QuaternionSafeLookRotation(vector); + torquePID.inputQuat = rotation; + torquePID.targetQuat = targetQuat; + rigidbody.angularVelocity = torquePID.UpdatePID(); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Projectile/UnseenHandHealingProjectile.cs b/ilspy_dump/ror2_csproj/RoR2.Projectile/UnseenHandHealingProjectile.cs new file mode 100644 index 0000000..fc8d9a9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Projectile/UnseenHandHealingProjectile.cs @@ -0,0 +1,53 @@ +using RoR2.Orbs; +using UnityEngine; + +namespace RoR2.Projectile; + +[RequireComponent(typeof(ProjectileController))] +public class UnseenHandHealingProjectile : MonoBehaviour, IOnDamageInflictedServerReceiver +{ + public bool addBarrier; + + public bool addHealing; + + public float fractionOfDamage; + + public float barrierPercent; + + private int chakraCount; + + public float chakraIncrease; + + private ProjectileController projectileController; + + private void Awake() + { + projectileController = GetComponent(); + } + + public void OnDamageInflictedServer(DamageReport damageReport) + { + if ((bool)projectileController.owner) + { + HealthComponent component = projectileController.owner.GetComponent(); + CharacterBody component2 = projectileController.owner.GetComponent(); + if (component2 != null) + { + chakraCount = component2.GetBuffCount(DLC2Content.Buffs.ChakraBuff); + } + if (addHealing && (bool)component) + { + HealOrb healOrb = new HealOrb(); + healOrb.origin = base.transform.position; + healOrb.target = component.body.mainHurtBox; + healOrb.healValue = damageReport.damageDealt * (fractionOfDamage + (float)chakraCount * chakraIncrease); + healOrb.overrideDuration = 0.3f; + OrbManager.instance.AddOrb(healOrb); + } + if (addBarrier) + { + component.AddBarrierAuthority(component2.baseMaxHealth * (barrierPercent + (float)chakraCount * chakraIncrease)); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/AdvancedFilterRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/AdvancedFilterRemoteGameProvider.cs new file mode 100644 index 0000000..9effd93 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/AdvancedFilterRemoteGameProvider.cs @@ -0,0 +1,189 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace RoR2.RemoteGameBrowser; + +public class AdvancedFilterRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + public new struct SearchFilters : IEquatable + { + public bool allowPassword; + + public int requiredSlots; + + public int maxPing; + + public int minMaxPlayers; + + public int maxMaxPlayers; + + public bool allowDifficultyEasy; + + public bool allowDifficultyNormal; + + public bool allowDifficultyHard; + + public bool showGamesWithRuleVoting; + + public bool showGamesWithoutRuleVoting; + + public bool allowInProgressGames; + + public bool Equals(SearchFilters other) + { + if (allowPassword == other.allowPassword && requiredSlots == other.requiredSlots && maxPing == other.maxPing && minMaxPlayers == other.minMaxPlayers && maxMaxPlayers == other.maxMaxPlayers && allowDifficultyEasy == other.allowDifficultyEasy && allowDifficultyNormal == other.allowDifficultyNormal && allowDifficultyHard == other.allowDifficultyHard && showGamesWithRuleVoting == other.showGamesWithRuleVoting && showGamesWithoutRuleVoting == other.showGamesWithoutRuleVoting) + { + return allowInProgressGames == other.allowInProgressGames; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is SearchFilters other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (((((((((((((((((((allowPassword.GetHashCode() * 397) ^ requiredSlots) * 397) ^ maxPing) * 397) ^ minMaxPlayers) * 397) ^ maxMaxPlayers) * 397) ^ allowDifficultyEasy.GetHashCode()) * 397) ^ allowDifficultyNormal.GetHashCode()) * 397) ^ allowDifficultyHard.GetHashCode()) * 397) ^ showGamesWithRuleVoting.GetHashCode()) * 397) ^ showGamesWithoutRuleVoting.GetHashCode()) * 397) ^ allowInProgressGames.GetHashCode(); + } + } + + private IRemoteGameProvider src; + + private new SearchFilters searchFilters; + + public new SearchFilters GetSearchFilters() + { + return searchFilters; + } + + public void SetSearchFilters(SearchFilters newSearchFilters) + { + if (!searchFilters.Equals(newSearchFilters)) + { + searchFilters = newSearchFilters; + SetDirty(); + } + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + RemoteGameInfo[] srcInfo = src.GetKnownGames(); + SearchFilters capturedSearchFilters = searchFilters; + return new Task(delegate + { + SearchFilters localSearchFilters = capturedSearchFilters; + bool[] array = new bool[srcInfo.Length]; + int num = 0; + for (int i = 0; i < srcInfo.Length; i++) + { + if (PassesFilters(in srcInfo[i])) + { + array[i] = true; + num++; + } + } + RemoteGameInfo[] array2 = new RemoteGameInfo[num]; + int j = 0; + int k = 0; + for (; j < array2.Length; j++) + { + for (; !array[k]; k++) + { + } + array2[j] = srcInfo[k++]; + } + return array2; + bool PassesFilters(in RemoteGameInfo remoteGameInfo) + { + if (!localSearchFilters.allowPassword && remoteGameInfo.hasPassword.GetValueOrDefault(false)) + { + return false; + } + if (localSearchFilters.requiredSlots > 0 && remoteGameInfo.availableSlots < localSearchFilters.requiredSlots) + { + return false; + } + if (localSearchFilters.maxPing > 0 && remoteGameInfo.ping.HasValue && remoteGameInfo.ping.Value > localSearchFilters.maxPing) + { + return false; + } + if (localSearchFilters.minMaxPlayers > remoteGameInfo.lesserMaxPlayers) + { + return false; + } + if (localSearchFilters.maxMaxPlayers < remoteGameInfo.greaterMaxPlayers) + { + return false; + } + DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(remoteGameInfo.currentDifficultyIndex ?? DifficultyIndex.Invalid); + if (difficultyDef == null) + { + return false; + } + if (!localSearchFilters.allowDifficultyEasy && remoteGameInfo.currentDifficultyIndex == DifficultyIndex.Easy) + { + return false; + } + if (!localSearchFilters.allowDifficultyNormal && remoteGameInfo.currentDifficultyIndex == DifficultyIndex.Normal) + { + return false; + } + if (!localSearchFilters.allowDifficultyHard && difficultyDef.countsAsHardMode) + { + return false; + } + if (!localSearchFilters.showGamesWithRuleVoting && remoteGameInfo.HasTag("rv1")) + { + return false; + } + if (!localSearchFilters.showGamesWithoutRuleVoting && remoteGameInfo.HasTag("rv0")) + { + return false; + } + if (!localSearchFilters.allowInProgressGames && !string.IsNullOrEmpty(remoteGameInfo.currentSceneName) && !(remoteGameInfo.currentSceneName == "lobby")) + { + return false; + } + return true; + } + }); + } + + public override bool RequestRefresh() + { + return src.RequestRefresh(); + } + + public AdvancedFilterRemoteGameProvider([NotNull] IRemoteGameProvider src) + { + this.src = src; + this.src.onNewInfoAvailable += base.SetDirty; + } + + public override void Dispose() + { + src.onNewInfoAvailable -= base.SetDirty; + base.Dispose(); + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return src?.IsBusy() ?? false; + } + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/AggregateRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/AggregateRemoteGameProvider.cs new file mode 100644 index 0000000..80a4001 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/AggregateRemoteGameProvider.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using HG; + +namespace RoR2.RemoteGameBrowser; + +public class AggregateRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + private IRemoteGameProvider[] providers = Array.Empty(); + + public override void Dispose() + { + for (int num = providers.Length - 1; num >= 0; num--) + { + OnProviderLost(providers[num]); + } + providers = Array.Empty(); + base.Dispose(); + } + + public override bool RequestRefresh() + { + IRemoteGameProvider[] array = providers; + for (int i = 0; i < array.Length; i++) + { + array[i].RequestRefresh(); + } + return true; + } + + public void AddProvider(IRemoteGameProvider provider) + { + ArrayUtils.ArrayAppend(ref providers, in provider); + OnProviderDiscovered(provider); + SetDirty(); + } + + public void RemoveProvider(IRemoteGameProvider provider) + { + int num = Array.IndexOf(providers, provider); + if (num != -1) + { + RemoveProviderAt(num); + } + } + + public void SetProviderAdded(IRemoteGameProvider provider, bool shouldUse) + { + int num = Array.IndexOf(providers, provider); + if (num == -1) + { + if (shouldUse) + { + AddProvider(provider); + } + } + else if (!shouldUse) + { + RemoveProviderAt(num); + } + } + + private void RemoveProviderAt(int index) + { + OnProviderLost(providers[index]); + ArrayUtils.ArrayRemoveAtAndResize(ref providers, index); + SetDirty(); + } + + private void OnProviderDiscovered(IRemoteGameProvider provider) + { + provider.onNewInfoAvailable += OnProviderNewInfoAvailable; + } + + private void OnProviderLost(IRemoteGameProvider provider) + { + provider.onNewInfoAvailable -= OnProviderNewInfoAvailable; + } + + private void OnProviderNewInfoAvailable() + { + SetDirty(); + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + IList providers = this.providers; + return new Task(delegate + { + cancellationToken.ThrowIfCancellationRequested(); + IEnumerable[] array = new IEnumerable[providers.Count]; + for (int i = 0; i < providers.Count; i++) + { + array[i] = providers[i].GetKnownGames(); + } + cancellationToken.ThrowIfCancellationRequested(); + int num = 0; + for (int j = 0; j < providers.Count; j++) + { + num += array[j].Count(); + } + cancellationToken.ThrowIfCancellationRequested(); + RemoteGameInfo[] array2 = new RemoteGameInfo[num]; + int k = 0; + int num2 = 0; + for (; k < providers.Count; k++) + { + cancellationToken.ThrowIfCancellationRequested(); + RemoteGameInfo[] knownGames = providers[k].GetKnownGames(); + foreach (RemoteGameInfo remoteGameInfo in knownGames) + { + array2[num2++] = remoteGameInfo; + } + } + return array2; + }); + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return IsAnyProviderBusy(); + } + return true; + bool IsAnyProviderBusy() + { + for (int i = 0; i < providers.Length; i++) + { + if (providers[i].IsBusy()) + { + return true; + } + } + return false; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/BaseAsyncRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/BaseAsyncRemoteGameProvider.cs new file mode 100644 index 0000000..1f9d624 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/BaseAsyncRemoteGameProvider.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace RoR2.RemoteGameBrowser; + +public abstract class BaseAsyncRemoteGameProvider : IRemoteGameProvider, IDisposable +{ + public struct SearchFilters : IEquatable + { + public bool allowMismatchedMods; + + public bool Equals(SearchFilters other) + { + return allowMismatchedMods == other.allowMismatchedMods; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is SearchFilters other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return allowMismatchedMods.GetHashCode(); + } + } + + protected struct TaskInfo + { + public Task task; + + public CancellationTokenSource cancellationTokenSource; + + public int taskNumber; + + public void Cancel() + { + cancellationTokenSource.Cancel(); + } + } + + private RemoteGameInfo[] gameInfos = Array.Empty(); + + private readonly object gameInfosLock = new object(); + + private readonly object isDirtyLock = new object(); + + private readonly object disposedLock = new object(); + + private readonly List activeTasks = new List(); + + private int taskNumberProvider; + + protected int maxTasks = 2; + + private bool isDirty; + + public bool refreshOnFiltersChanged = true; + + protected SearchFilters searchFilters = new SearchFilters + { + allowMismatchedMods = false + }; + + protected bool disposed { get; private set; } + + public event Action onNewInfoAvailable; + + public SearchFilters GetSearchFilters() + { + return searchFilters; + } + + public void SetSearchFilters(SearchFilters newSearchFilters) + { + if (!searchFilters.Equals(newSearchFilters)) + { + searchFilters = newSearchFilters; + if (refreshOnFiltersChanged) + { + RequestRefresh(); + } + SetDirty(); + } + } + + protected void SetDirty() + { + lock (disposedLock) + { + if (disposed) + { + return; + } + lock (isDirtyLock) + { + if (!isDirty) + { + isDirty = true; + RoR2Application.onNextUpdate += DirtyUpdate; + } + } + } + } + + protected void DirtyUpdate() + { + lock (disposedLock) + { + if (disposed) + { + return; + } + lock (activeTasks) + { + if (activeTasks.Count >= maxTasks) + { + return; + } + lock (isDirtyLock) + { + isDirty = false; + GenerateNewTask(); + } + } + } + } + + private void GenerateNewTask() + { + CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + CancellationToken cancellationToken = cancellationTokenSource.Token; + Task innerTask = CreateTask(cancellationToken); + lock (activeTasks) + { + Task task = Task.Run(async delegate + { + try + { + innerTask.Start(); + RemoteGameInfo[] array = await innerTask; + lock (gameInfosLock) + { + cancellationToken.ThrowIfCancellationRequested(); + gameInfos = array; + lock (activeTasks) + { + for (int i = 0; i < activeTasks.Count; i++) + { + TaskInfo taskInfo = activeTasks[i]; + if (taskInfo.cancellationTokenSource == cancellationTokenSource) + { + OnTaskComplete(taskInfo); + break; + } + } + } + } + } + finally + { + lock (activeTasks) + { + for (int num = activeTasks.Count - 1; num >= 0; num--) + { + if (activeTasks[num].cancellationTokenSource == cancellationTokenSource) + { + activeTasks.RemoveAt(num); + break; + } + } + } + } + }, cancellationToken); + activeTasks.Add(new TaskInfo + { + task = task, + cancellationTokenSource = cancellationTokenSource, + taskNumber = taskNumberProvider++ + }); + } + } + + protected abstract Task CreateTask(CancellationToken cancellationToken); + + protected void OnTaskComplete(TaskInfo taskInfo) + { + lock (activeTasks) + { + for (int num = activeTasks.Count - 1; num >= 0; num--) + { + if (activeTasks[num].taskNumber < taskInfo.taskNumber) + { + activeTasks[num].Cancel(); + } + } + } + this.onNewInfoAvailable?.Invoke(); + } + + public virtual void Dispose() + { + lock (disposedLock) + { + disposed = true; + lock (activeTasks) + { + foreach (TaskInfo activeTask in activeTasks) + { + activeTask.Cancel(); + } + } + } + } + + public abstract bool RequestRefresh(); + + public RemoteGameInfo[] GetKnownGames() + { + return gameInfos; + } + + public virtual bool IsBusy() + { + return activeTasks.Count > 0; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/EOSLobbyRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/EOSLobbyRemoteGameProvider.cs new file mode 100644 index 0000000..db4672b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/EOSLobbyRemoteGameProvider.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Epic.OnlineServices; +using Epic.OnlineServices.Lobby; +using HG; +using RoR2.Networking; + +namespace RoR2.RemoteGameBrowser; + +public class EOSLobbyRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + private readonly List lobbyList = new List(); + + private int waitingForLobbyCount; + + private static readonly char[] tagsSeparator = new char[1] { ',' }; + + private EOSLobbyManager.Filter BuildFilter() + { + EOSLobbyManager.Filter filter = new EOSLobbyManager.Filter(); + if (!searchFilters.allowMismatchedMods) + { + AttributeData attributeData = default(AttributeData); + attributeData.Key = "_mh"; + attributeData.Value = NetworkModCompatibilityHelper.networkModHash; + AttributeData item = attributeData; + filter.SearchData.Add(item); + } + return filter; + } + + public override bool RequestRefresh() + { + EOSLobbyManager.Filter filter = BuildFilter(); + bool num = (PlatformSystems.lobbyManager as EOSLobbyManager).RequestLobbyList(this, filter, OnLobbyListReceived); + if (num) + { + waitingForLobbyCount++; + } + return num; + } + + private void OnLobbyListReceived(List lobbies) + { + if (base.disposed) + { + return; + } + waitingForLobbyCount--; + lock (lobbyList) + { + lobbyList.Clear(); + lobbyList.AddRange(lobbies); + SetDirty(); + } + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + LobbyDetails[] lobbies; + lock (lobbyList) + { + lobbies = lobbyList.ToArray(); + } + return new Task(delegate + { + RemoteGameInfo[] array = new RemoteGameInfo[lobbies.Length]; + for (int i = 0; i < lobbies.Length; i++) + { + CreateRemoteGameInfo(lobbies[i], out array[i]); + } + return array; + }, cancellationToken); + } + + private static void CreateRemoteGameInfo(LobbyDetails lobby, out RemoteGameInfo result) + { + result = default(RemoteGameInfo); + LobbyDetailsCopyInfoOptions options = default(LobbyDetailsCopyInfoOptions); + if (lobby.CopyInfo(ref options, out var outLobbyDetailsInfo) == Result.Success) + { + result.name = outLobbyDetailsInfo.Value.LobbyOwnerUserId.ToString(); + result.lobbyName = outLobbyDetailsInfo.Value.LobbyId; + result.lobbyIdStr = outLobbyDetailsInfo.Value.LobbyId; + string lobbyStringValue = EOSLobbyManager.GetLobbyStringValue(lobby, "_map"); + result.serverIdStr = EOSLobbyManager.GetLobbyStringValue(lobby, "server_id"); + result.serverAddress = GetAddressPortPair("server_address"); + result.serverName = EOSLobbyManager.GetLobbyStringValue(lobby, "_svnm"); + result.lobbyPlayerCount = GetInt("player_count", 1, int.MaxValue) ?? 1; + result.lobbyMaxPlayers = GetInt("total_max_players", 1, int.MaxValue) ?? 1; + result.serverPlayerCount = GetInt("_svplc", 0, int.MaxValue); + result.serverMaxPlayers = GetInt("_svmpl", 0, int.MaxValue); + result.inGame = result.IsServerIdValid() || result.serverAddress.HasValue; + result.currentSceneName = lobbyStringValue; + if (lobbyStringValue != null) + { + result.currentSceneIndex = SceneCatalog.GetSceneDefFromSceneName(lobbyStringValue)?.sceneDefIndex; + } + result.requestRefreshImplementation = RemoteGameInfoRequestRefresh; + result.getPlayersImplementation = RemoteGameInfoGetPlayers; + result.getRuleBookImplementation = RemoteGameInfoGetRuleBook; + result.userData = lobby; + result.hasPassword = GetBool("_pw"); + result.gameModeName = EOSLobbyManager.GetLobbyStringValue(lobby, "_svgm"); + result.buildId = EOSLobbyManager.GetLobbyStringValue(lobby, "build_id") ?? "UNKNOWN"; + result.modHash = EOSLobbyManager.GetLobbyStringValue(lobby, "_mh") ?? "UNKNOWN"; + result.SetTags(GetTags("_svtags")); + result.CalcExtraFields(); + } + AddressPortPair? GetAddressPortPair(string key) + { + if (!AddressPortPair.TryParse(EOSLobbyManager.GetLobbyStringValue(lobby, key), out var addressPortPair)) + { + return null; + } + return addressPortPair; + } + bool? GetBool(string key) + { + return GetInt(key, int.MinValue, int.MaxValue) > 0; + } + int? GetInt(string key, int min, int max) + { + if (int.TryParse(EOSLobbyManager.GetLobbyStringValue(lobby, key), out var result2) && min <= result2 && result2 <= max) + { + return result2; + } + return null; + } + string[] GetTags(string key) + { + return EOSLobbyManager.GetLobbyStringValue(lobby, key)?.Split(tagsSeparator, StringSplitOptions.None); + } + } + + private static void RemoteGameInfoRequestRefresh(in RemoteGameInfo remoteGameInfo, RemoteGameInfo.RequestRefreshSuccessCallback successCallback, Action failureCallback, bool fetchDetails) + { + if (remoteGameInfo.userData is LobbyDetails) + { + CreateRemoteGameInfo(remoteGameInfo.userData as LobbyDetails, out var result); + successCallback?.Invoke(in result); + } + } + + private static bool RemoteGameInfoGetRuleBook(in RemoteGameInfo remoteGameInfo, RuleBook dest) + { + if (remoteGameInfo.userData is LobbyDetails lobbyDetails) + { + KeyValueUnsplitter keyValueUnsplitter = new KeyValueUnsplitter("rulebook"); + List> list = CollectionPool, List>>.RentCollection(); + try + { + LobbyDetailsGetAttributeCountOptions options = default(LobbyDetailsGetAttributeCountOptions); + uint num = 0u; + for (uint attributeCount = lobbyDetails.GetAttributeCount(ref options); num < attributeCount; num++) + { + LobbyDetailsCopyAttributeByIndexOptions lobbyDetailsCopyAttributeByIndexOptions = default(LobbyDetailsCopyAttributeByIndexOptions); + lobbyDetailsCopyAttributeByIndexOptions.AttrIndex = num; + LobbyDetailsCopyAttributeByIndexOptions options2 = lobbyDetailsCopyAttributeByIndexOptions; + if (lobbyDetails.CopyAttributeByIndex(ref options2, out var outAttribute) == Result.Success) + { + AttributeData value = outAttribute.Value.Data.Value; + list.Add(new KeyValuePair(value.Key.ToString().ToLower(), value.Value.AsUtf8.ToString().ToLower())); + } + } + string value2 = keyValueUnsplitter.GetValue(list); + if (!string.IsNullOrEmpty(value2)) + { + RuleBook.ReadBase64(value2, dest); + return true; + } + } + finally + { + list = CollectionPool, List>>.ReturnCollection(list); + } + } + return false; + } + + private static void RemoteGameInfoGetPlayers(in RemoteGameInfo remoteGameInfo, List output) + { + if (remoteGameInfo.userData is LobbyDetails lobbyDetails) + { + LobbyDetailsGetMemberCountOptions options = default(LobbyDetailsGetMemberCountOptions); + uint memberCount = lobbyDetails.GetMemberCount(ref options); + for (uint num = 0u; num < memberCount; num++) + { + output.Add(new RemotePlayerInfo + { + id = 0uL, + name = "???" + }); + } + } + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return waitingForLobbyCount > 0; + } + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/IRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/IRemoteGameProvider.cs new file mode 100644 index 0000000..e8f1706 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/IRemoteGameProvider.cs @@ -0,0 +1,14 @@ +using System; + +namespace RoR2.RemoteGameBrowser; + +public interface IRemoteGameProvider +{ + event Action onNewInfoAvailable; + + bool RequestRefresh(); + + RemoteGameInfo[] GetKnownGames(); + + bool IsBusy(); +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/PageRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/PageRemoteGameProvider.cs new file mode 100644 index 0000000..7229b84 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/PageRemoteGameProvider.cs @@ -0,0 +1,137 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.RemoteGameBrowser; + +public class PageRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + private int gamesPerPage = 1; + + private int pageIndex; + + private int maxPages; + + private readonly IRemoteGameProvider source; + + public PageRemoteGameProvider([NotNull] IRemoteGameProvider source) + { + this.source = source; + source.onNewInfoAvailable += OnSourceNewInfoAvailable; + maxTasks = 1; + } + + public override void Dispose() + { + source.onNewInfoAvailable -= OnSourceNewInfoAvailable; + base.Dispose(); + } + + private void OnSourceNewInfoAvailable() + { + SetDirty(); + } + + public void SetGamesPerPage(int newGamesPerPage) + { + if (newGamesPerPage < 1) + { + newGamesPerPage = 1; + } + if (newGamesPerPage != gamesPerPage) + { + gamesPerPage = newGamesPerPage; + SetDirty(); + } + } + + public bool CanGoToNextPage() + { + return pageIndex + 1 < maxPages; + } + + public bool CanGoToPreviousPage() + { + return pageIndex - 1 >= 0; + } + + public bool GoToNextPage() + { + lock (this) + { + if (!CanGoToNextPage()) + { + return false; + } + pageIndex++; + SetDirty(); + return true; + } + } + + public bool GoToPreviousPage() + { + lock (this) + { + if (!CanGoToPreviousPage()) + { + return false; + } + pageIndex--; + SetDirty(); + return true; + } + } + + public void GetCurrentPageInfo(out int pageIndex, out int maxPages) + { + lock (this) + { + pageIndex = this.pageIndex; + maxPages = this.maxPages; + } + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + return new Task(delegate + { + RemoteGameInfo[] knownGames = source.GetKnownGames(); + lock (this) + { + maxPages = (knownGames.Length + gamesPerPage - 1) / gamesPerPage; + pageIndex = Math.Max(Math.Min(pageIndex, maxPages - 1), 0); + int num = Math.Min(gamesPerPage * pageIndex, knownGames.Length); + int num2 = Mathf.Min(num + gamesPerPage, knownGames.Length); + if (num2 == num) + { + return Array.Empty(); + } + RemoteGameInfo[] array = new RemoteGameInfo[num2 - num]; + int i = num; + int num3 = 0; + for (; i < num2; i++) + { + array[num3++] = knownGames[i]; + } + return array; + } + }); + } + + public override bool RequestRefresh() + { + return source.RequestRefresh(); + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return source?.IsBusy() ?? false; + } + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameBrowserController.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameBrowserController.cs new file mode 100644 index 0000000..101d847 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameBrowserController.cs @@ -0,0 +1,501 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using HG; +using JetBrains.Annotations; +using RoR2.UI; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.RemoteGameBrowser; + +public class RemoteGameBrowserController : MonoBehaviour +{ + private class FilterInfo + { + public RemoteGameFilterValue value; + + public string token; + + public Func getUIValue; + + public Action setUIValue; + + public GameObject controlGameObject; + + public Component controlMainComponent; + + public LanguageTextMeshController labelController; + } + + private class FilterManager + { + [MeansImplicitUse(ImplicitUseKindFlags.Assign)] + private class SetupAttribute : Attribute + { + public RemoteGameFilterValue defaultValue; + + public int minValue; + + public int maxValue; + + public SetupAttribute(bool defaultValue) + { + this.defaultValue = defaultValue; + } + + public SetupAttribute(int defaultValue, int minValue = int.MinValue, int maxValue = int.MaxValue) + { + this.defaultValue = defaultValue; + this.minValue = minValue; + this.maxValue = maxValue; + } + + public SetupAttribute(string defaultValue) + { + this.defaultValue = defaultValue; + } + } + + public readonly RemoteGameBrowserController owner; + + private RectTransform currentContainer; + + public List allFilters = new List(); + + [Setup(true)] + public FilterInfo showDedicatedServers; + + [Setup(true)] + public FilterInfo showLobbies; + + [Setup(true)] + public FilterInfo showDifficultyEasyGames; + + [Setup(true)] + public FilterInfo showDifficultyNormalGames; + + [Setup(true)] + public FilterInfo showDifficultyHardGames; + + [Setup(true)] + public FilterInfo showGamesWithRuleVoting; + + [Setup(true)] + public FilterInfo showGamesWithoutRuleVoting; + + [Setup(true)] + public FilterInfo showPasswordedGames; + + [Setup(0, int.MinValue, int.MaxValue, minValue = 0, maxValue = 999)] + public FilterInfo maxPing; + + [Setup(false)] + public FilterInfo mustHavePlayers; + + [Setup(true)] + public FilterInfo mustHaveEnoughSlots; + + [Setup(1, int.MinValue, int.MaxValue, minValue = 1)] + public FilterInfo minMaxPlayers; + + [Setup(16, int.MinValue, int.MaxValue, minValue = 1)] + public FilterInfo maxMaxPlayers; + + [Setup("")] + public FilterInfo requiredTags; + + [Setup("")] + public FilterInfo forbiddenTags; + + [Setup(false)] + public FilterInfo showStartedGames; + + [Setup(true)] + public FilterInfo hideIncompatibleGames; + + public FilterManager(RemoteGameBrowserController owner) + { + this.owner = owner; + currentContainer = owner.filterControlContainer; + GenerateFilters(); + } + + private FilterInfo AddFilter(string token, RemoteGameFilterValue defaultValue, GameObject controlPrefab, Func getUIValue, Action setUIValue) where T : Component + { + FilterInfo filterInfo = new FilterInfo + { + token = token, + value = defaultValue, + controlGameObject = UnityEngine.Object.Instantiate(controlPrefab, currentContainer), + getUIValue = getUIValue, + setUIValue = setUIValue + }; + filterInfo.controlMainComponent = filterInfo.controlGameObject.transform.Find("MainControl").GetComponent(); + filterInfo.labelController = filterInfo.controlGameObject.transform.Find("NameLabel").GetComponent(); + filterInfo.controlGameObject.SetActive(value: true); + filterInfo.setUIValue(filterInfo.controlMainComponent, defaultValue); + allFilters.Add(filterInfo); + return filterInfo; + } + + private FilterInfo AddBoolFilter(string token, bool defaultValue) + { + return AddFilter(token, defaultValue, owner.togglePrefab, GetUIValue, SetUIValue); + static RemoteGameFilterValue? GetUIValue(Component c) + { + return ((MPToggle)c).isOn; + } + static void SetUIValue(Component c, RemoteGameFilterValue value) + { + ((MPToggle)c).isOn = value.boolValue; + } + } + + private FilterInfo AddIntFilter(string token, int defaultValue, int minValue = int.MinValue, int maxValue = int.MaxValue, uint minDigits = 1u, uint maxDigits = uint.MaxValue) + { + FilterInfo filterInfo = AddFilter(token, defaultValue, owner.textFieldPrefab, GetUIValue, SetUIValue); + ((TMP_InputField)filterInfo.controlMainComponent).characterValidation = TMP_InputField.CharacterValidation.Integer; + return filterInfo; + RemoteGameFilterValue? GetUIValue(Component c) + { + if (int.TryParse(((TMP_InputField)c).text, out var result)) + { + return Mathf.Clamp(result, minValue, maxValue); + } + return null; + } + void SetUIValue(Component c, RemoteGameFilterValue v) + { + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + stringBuilder.AppendInt(v.intValue, minDigits, maxDigits); + ((TMP_InputField)c).SetTextWithoutNotify(stringBuilder.ToString()); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } + } + + private FilterInfo AddStringFilter(string token, string defaultValue) + { + return AddFilter(token, defaultValue, owner.textFieldPrefab, GetUIValue, SetUIValue); + static RemoteGameFilterValue? GetUIValue(Component c) + { + return ((TMP_InputField)c).text; + } + static void SetUIValue(Component c, RemoteGameFilterValue v) + { + ((TMP_InputField)c).SetTextWithoutNotify(v.stringValue); + } + } + + private void GenerateFilters() + { + Regex regex = new Regex("([A-Z]?[a-z]+)"); + FieldInfo[] fields = typeof(FilterManager).GetFields(); + foreach (FieldInfo fieldInfo in fields) + { + if (fieldInfo.FieldType != typeof(FilterInfo)) + { + continue; + } + SetupAttribute customAttribute = CustomAttributeExtensions.GetCustomAttribute(fieldInfo); + if (customAttribute == null) + { + return; + } + string name = fieldInfo.Name; + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + stringBuilder.Append("GAME_BROWSER_FILTER"); + foreach (Match item in regex.Matches(name)) + { + stringBuilder.Append("_"); + for (int j = 0; j < item.Length; j++) + { + stringBuilder.Append(char.ToUpperInvariant(name[item.Index + j])); + } + } + string token = stringBuilder.ToString(); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + FilterInfo filterInfo = null; + filterInfo = customAttribute.defaultValue.valueType switch + { + RemoteGameFilterValue.ValueType.Bool => AddBoolFilter(token, customAttribute.defaultValue.boolValue), + RemoteGameFilterValue.ValueType.Int => AddIntFilter(token, customAttribute.defaultValue.intValue, customAttribute.minValue, customAttribute.maxValue), + RemoteGameFilterValue.ValueType.String => AddStringFilter(token, customAttribute.defaultValue.stringValue), + _ => throw new ArgumentOutOfRangeException(), + }; + fieldInfo.SetValue(this, filterInfo); + filterInfo.labelController.token = filterInfo.token; + } + CopyInternalValuesToUI(); + } + + public void CopyInternalValuesToUI() + { + foreach (FilterInfo allFilter in allFilters) + { + allFilter.setUIValue(allFilter.controlMainComponent, allFilter.value); + } + } + + public void CopyUIValuesToInternal() + { + foreach (FilterInfo allFilter in allFilters) + { + allFilter.value = allFilter.getUIValue(allFilter.controlMainComponent) ?? allFilter.value; + } + } + } + + public GameObject cardPrefab; + + public RectTransform cardContainer; + + public MPButton previousPageButton; + + public MPButton nextPageButton; + + public HGTextMeshProUGUI pageNumberLabel; + + public GameObject togglePrefab; + + public GameObject textFieldPrefab; + + public RectTransform filterControlContainer; + + public MPDropdown sortTypeDropdown; + + public MPToggle sortAscendToggle; + + public Graphic busyIcon; + + private UIElementAllocator cardAllocator; + + private bool displayDataDirty; + + private float cardPrefabHeight = 1f; + + private float initialRequestTime = float.PositiveInfinity; + + private IRemoteGameProvider primaryRemoteGameProvider; + + private PageRemoteGameProvider pageRemoteGameProvider; + + private SortRemoteGameProvider sortRemoteGameProvider; + + private AdvancedFilterRemoteGameProvider advancedFilterRemoteGameProvider; + + private AggregateRemoteGameProvider aggregateRemoteGameProvider; + + private SteamworksServerRemoteGameProvider serverRemoteGameProvider; + + private BaseAsyncRemoteGameProvider lobbyRemoteGameProvider; + + private FilterManager filters; + + private void Awake() + { + cardAllocator = new UIElementAllocator(cardContainer, cardPrefab); + serverRemoteGameProvider = new SteamworksServerRemoteGameProvider(SteamworksServerRemoteGameProvider.Mode.Internet) + { + refreshOnFiltersChanged = true + }; + if (PlatformSystems.ShouldUseEpicOnlineSystems) + { + lobbyRemoteGameProvider = new EOSLobbyRemoteGameProvider(); + } + else + { + lobbyRemoteGameProvider = new SteamworksLobbyRemoteGameProvider(); + } + aggregateRemoteGameProvider = new AggregateRemoteGameProvider(); + advancedFilterRemoteGameProvider = new AdvancedFilterRemoteGameProvider(aggregateRemoteGameProvider); + sortRemoteGameProvider = new SortRemoteGameProvider(advancedFilterRemoteGameProvider); + pageRemoteGameProvider = new PageRemoteGameProvider(sortRemoteGameProvider); + primaryRemoteGameProvider = pageRemoteGameProvider; + primaryRemoteGameProvider.onNewInfoAvailable += OnNewInfoAvailable; + previousPageButton.onClick.AddListener(OnPreviousPageButtonClick); + nextPageButton.onClick.AddListener(OnNextPageButtonClick); + cardPrefabHeight = cardPrefab.GetComponent().preferredHeight; + } + + private void Start() + { + filters = new FilterManager(this); + initialRequestTime = Time.unscaledTime + 0.2f; + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.F5) || initialRequestTime <= Time.unscaledTime) + { + initialRequestTime = float.PositiveInfinity; + RequestRefresh(); + } + UpdateSearchFiltersInternal(); + UpdateSorting(); + float height = cardContainer.rect.height; + float num = cardPrefabHeight; + int gamesPerPage = Mathf.FloorToInt(height / num); + pageRemoteGameProvider.SetGamesPerPage(gamesPerPage); + previousPageButton.interactable = pageRemoteGameProvider.CanGoToPreviousPage(); + nextPageButton.interactable = pageRemoteGameProvider.CanGoToNextPage(); + if (displayDataDirty) + { + SetDisplayData(primaryRemoteGameProvider.GetKnownGames()); + } + UpdateBusyIcon(); + } + + private void OnDestroy() + { + pageRemoteGameProvider.Dispose(); + sortRemoteGameProvider.Dispose(); + advancedFilterRemoteGameProvider.Dispose(); + aggregateRemoteGameProvider.Dispose(); + lobbyRemoteGameProvider.Dispose(); + serverRemoteGameProvider.Dispose(); + } + + private void OnEnable() + { + primaryRemoteGameProvider.RequestRefresh(); + RebuildSortTypeDropdown(); + } + + private void OnPreviousPageButtonClick() + { + pageRemoteGameProvider.GoToPreviousPage(); + } + + private void OnNextPageButtonClick() + { + pageRemoteGameProvider.GoToNextPage(); + } + + public void RequestRefresh() + { + primaryRemoteGameProvider.RequestRefresh(); + } + + private void OnNewInfoAvailable() + { + displayDataDirty = true; + } + + private void SetDisplayData(IList remoteGameInfos) + { + displayDataDirty = false; + cardAllocator.AllocateElements(remoteGameInfos.Count); + ReadOnlyCollection elements = cardAllocator.elements; + for (int i = 0; i < elements.Count; i++) + { + elements[i].SetDisplayData(remoteGameInfos[i]); + } + if ((bool)pageNumberLabel) + { + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + pageRemoteGameProvider.GetCurrentPageInfo(out var pageIndex, out var maxPages); + stringBuilder.AppendInt(pageIndex + 1).Append("/").AppendInt(Math.Max(maxPages, 1)); + pageNumberLabel.SetText(stringBuilder); + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } + } + + private void UpdateSearchFiltersInternal() + { + filters.CopyUIValuesToInternal(); + if (!PlatformSystems.ShouldUseEpicOnlineSystems) + { + aggregateRemoteGameProvider.SetProviderAdded(serverRemoteGameProvider, filters.showDedicatedServers.value.boolValue); + SteamworksServerRemoteGameProvider.SearchFilters searchFilters = serverRemoteGameProvider.GetSearchFilters(); + searchFilters.allowDedicatedServers = filters.showDedicatedServers.value.boolValue; + searchFilters.allowListenServers = true; + searchFilters.mustNotBeFull = filters.mustHaveEnoughSlots.value.boolValue; + searchFilters.mustHavePlayers = filters.mustHavePlayers.value.boolValue; + searchFilters.requiredTags = filters.requiredTags.value.stringValue; + searchFilters.forbiddenTags = filters.forbiddenTags.value.stringValue; + searchFilters.allowInProgressGames = filters.showStartedGames.value.boolValue; + searchFilters.allowMismatchedMods = !filters.hideIncompatibleGames.value.boolValue; + serverRemoteGameProvider.SetSearchFilters(searchFilters); + } + aggregateRemoteGameProvider.SetProviderAdded(lobbyRemoteGameProvider, filters.showLobbies.value.boolValue); + BaseAsyncRemoteGameProvider.SearchFilters searchFilters2 = lobbyRemoteGameProvider.GetSearchFilters(); + searchFilters2.allowMismatchedMods = !filters.hideIncompatibleGames.value.boolValue; + lobbyRemoteGameProvider.SetSearchFilters(searchFilters2); + int requiredSlots = 0; + if (!filters.mustHaveEnoughSlots.value.boolValue && PlatformSystems.lobbyManager.calculatedTotalPlayerCount > 0) + { + requiredSlots = PlatformSystems.lobbyManager.calculatedTotalPlayerCount; + } + AdvancedFilterRemoteGameProvider.SearchFilters searchFilters3 = advancedFilterRemoteGameProvider.GetSearchFilters(); + searchFilters3.allowPassword = filters.showPasswordedGames.value.boolValue; + searchFilters3.minMaxPlayers = filters.minMaxPlayers.value.intValue; + searchFilters3.maxMaxPlayers = filters.maxMaxPlayers.value.intValue; + searchFilters3.maxPing = filters.maxPing.value.intValue; + searchFilters3.requiredSlots = requiredSlots; + searchFilters3.allowDifficultyEasy = filters.showDifficultyEasyGames.value.boolValue; + searchFilters3.allowDifficultyNormal = filters.showDifficultyNormalGames.value.boolValue; + searchFilters3.allowDifficultyHard = filters.showDifficultyHardGames.value.boolValue; + searchFilters3.showGamesWithRuleVoting = filters.showGamesWithRuleVoting.value.boolValue; + searchFilters3.showGamesWithoutRuleVoting = filters.showGamesWithoutRuleVoting.value.boolValue; + searchFilters3.allowInProgressGames = filters.showStartedGames.value.boolValue; + advancedFilterRemoteGameProvider.SetSearchFilters(searchFilters3); + } + + private void RebuildSortTypeDropdown() + { + List list = CollectionPool>.RentCollection(); + sortTypeDropdown.ClearOptions(); + for (int i = 0; i < SortRemoteGameProvider.sorters.Length; i++) + { + list.Add(Language.GetString(SortRemoteGameProvider.sorters[i].nameToken)); + } + sortTypeDropdown.AddOptions(list); + SortRemoteGameProvider.Parameters parameters = sortRemoteGameProvider.GetParameters(); + sortTypeDropdown.SetValueWithoutNotify(parameters.sorterIndex); + CollectionPool>.ReturnCollection(list); + } + + private void UpdateSorting() + { + SortRemoteGameProvider.Parameters parameters = sortRemoteGameProvider.GetParameters(); + parameters.ascending = sortAscendToggle.isOn; + parameters.sorterIndex = sortTypeDropdown.value; + sortRemoteGameProvider.SetParameters(parameters); + } + + private void UpdateBusyIcon() + { + if ((bool)busyIcon) + { + Color color = busyIcon.color; + float num = 1f; + if (!primaryRemoteGameProvider.IsBusy()) + { + num = color.a - Time.unscaledDeltaTime; + } + if (num != color.a) + { + color.a = num; + busyIcon.color = color; + } + } + } + + [ContextMenu("Copy Filter Tokens")] + private void CopyFilterTokens() + { + StringBuilder stringBuilder = new StringBuilder(); + foreach (FilterInfo allFilter in filters.allFilters) + { + stringBuilder.Append('"').Append(allFilter.token).Append('"') + .Append(": \"\",") + .AppendLine(); + } + GUIUtility.systemCopyBuffer = stringBuilder.ToString(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameCardController.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameCardController.cs new file mode 100644 index 0000000..dcbfb04 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameCardController.cs @@ -0,0 +1,105 @@ +using System.Collections.Generic; +using System.Text; +using HG; +using RoR2.UI; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.RemoteGameBrowser; + +public class RemoteGameCardController : MonoBehaviour +{ + public TextMeshProUGUI nameLabel; + + public TextMeshProUGUI playerCountLabel; + + public TextMeshProUGUI pingLabel; + + public TextMeshProUGUI tagsLabel; + + public TextMeshProUGUI typeLabel; + + public ArtifactDisplayPanelController artifactDisplayPanelController; + + public RawImage mapImage; + + public GameObject passwordIconObject; + + public GameObject difficultyIconObject; + + public Image difficultyIcon; + + private static List artifactBuffer = new List(); + + private RemoteGameInfo currentGameInfo; + + public void OpenCurrentGameDetails() + { + RectTransform parent = (RectTransform)RoR2Application.instance.mainCanvas.transform; + GameObject obj = Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/UI/RemoteGameBrowser/RemoteGameDetailsPanel"), parent); + RectTransform obj2 = (RectTransform)obj.transform; + Vector2 vector = -(obj2.rect.size / 2f); + vector.y = 0f - vector.y; + obj2.localPosition = Vector2.zero + vector; + obj.GetComponent().SetGameInfo(currentGameInfo); + } + + public void SetDisplayData(RemoteGameInfo remoteGameInfo) + { + currentGameInfo = remoteGameInfo; + StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder(); + Texture texture = null; + if (remoteGameInfo.currentSceneIndex.HasValue) + { + texture = SceneCatalog.GetSceneDef(remoteGameInfo.currentSceneIndex.Value)?.previewTexture; + } + mapImage.enabled = texture != null; + mapImage.texture = texture; + passwordIconObject.SetActive(remoteGameInfo.hasPassword.GetValueOrDefault()); + playerCountLabel.SetText(stringBuilder.Clear().AppendInt(remoteGameInfo.lobbyPlayerCount ?? remoteGameInfo.serverPlayerCount.GetValueOrDefault()).Append("/") + .AppendInt(remoteGameInfo.lobbyMaxPlayers ?? remoteGameInfo.serverMaxPlayers.GetValueOrDefault())); + if (remoteGameInfo.currentDifficultyIndex.HasValue) + { + DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(remoteGameInfo.currentDifficultyIndex.Value); + difficultyIcon.sprite = difficultyDef?.GetIconSprite(); + difficultyIcon.enabled = true; + } + else + { + difficultyIcon.enabled = false; + } + nameLabel.SetText(remoteGameInfo.serverName ?? remoteGameInfo.lobbyName); + stringBuilder.Clear(); + if (remoteGameInfo.ping.HasValue) + { + stringBuilder.AppendInt(remoteGameInfo.ping ?? (-1)); + } + else + { + stringBuilder.Append("N/A"); + } + pingLabel.SetText(stringBuilder); + stringBuilder.Clear(); + if (remoteGameInfo.tags != null && remoteGameInfo.tags.Length != 0) + { + stringBuilder.Append(remoteGameInfo.tags[0]); + for (int i = 1; i < remoteGameInfo.tags.Length; i++) + { + stringBuilder.Append(", ").Append(remoteGameInfo.tags[i]); + } + } + tagsLabel.SetText(stringBuilder); + artifactBuffer.Clear(); + foreach (ArtifactDef enabledArtifact in remoteGameInfo.GetEnabledArtifacts()) + { + artifactBuffer.Add(enabledArtifact); + } + List.Enumerator enabledArtifacts = artifactBuffer.GetEnumerator(); + if ((bool)artifactDisplayPanelController) + { + artifactDisplayPanelController.SetDisplayData(ref enabledArtifacts); + } + HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameFilterValue.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameFilterValue.cs new file mode 100644 index 0000000..b7d988e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameFilterValue.cs @@ -0,0 +1,55 @@ +namespace RoR2.RemoteGameBrowser; + +public struct RemoteGameFilterValue +{ + public enum ValueType + { + Bool, + Int, + String + } + + public readonly ValueType valueType; + + public readonly int intValue; + + public readonly string stringValue; + + public bool boolValue => intValue != 0; + + public RemoteGameFilterValue(bool boolValue) + { + valueType = ValueType.Bool; + intValue = (boolValue ? 1 : 0); + stringValue = null; + } + + public RemoteGameFilterValue(int intValue) + { + valueType = ValueType.Int; + this.intValue = intValue; + stringValue = null; + } + + public RemoteGameFilterValue(string stringValue) + { + valueType = ValueType.String; + intValue = 0; + this.stringValue = stringValue; + } + + public static implicit operator RemoteGameFilterValue(bool boolValue) + { + return new RemoteGameFilterValue(boolValue); + } + + public static implicit operator RemoteGameFilterValue(int intValue) + { + return new RemoteGameFilterValue(intValue); + } + + public static implicit operator RemoteGameFilterValue(string stringValue) + { + return new RemoteGameFilterValue(stringValue); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameInfo.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameInfo.cs new file mode 100644 index 0000000..e4e9520 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteGameInfo.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using JetBrains.Annotations; +using RoR2.Networking; + +namespace RoR2.RemoteGameBrowser; + +public struct RemoteGameInfo +{ + public delegate void GetPlayersDelegate(in RemoteGameInfo remoteGameInfo, [NotNull] List output); + + public delegate void RequestRefreshDelegate(in RemoteGameInfo remoteGameInfo, [CanBeNull] RequestRefreshSuccessCallback successCallback, [CanBeNull] Action failureCallback, bool fetchDetails); + + public delegate void RequestRefreshSuccessCallback(in RemoteGameInfo remoteGameInfo); + + public delegate bool GetRuleBookDelegate(in RemoteGameInfo remoteGameInfo, RuleBook dest); + + public struct ArtifactEnumerator : IEnumerator, IEnumerator, IDisposable + { + public readonly string tagSource; + + private int readPos; + + public ArtifactDef Current => ArtifactCatalog.GetArtifactDef((ArtifactIndex)(tagSource[readPos] - 48)); + + object IEnumerator.Current => Current; + + public ArtifactEnumerator(string tagSource) + { + this.tagSource = tagSource; + readPos = 1; + } + + public bool MoveNext() + { + readPos++; + return readPos < tagSource.Length; + } + + public void Reset() + { + readPos = 1; + } + + public void Dispose() + { + } + } + + public struct ArtifactEnumerable + { + public readonly string tagSource; + + public ArtifactEnumerable(string tagSource) + { + this.tagSource = tagSource; + } + + public ArtifactEnumerator GetEnumerator() + { + ArtifactEnumerator result = new ArtifactEnumerator(tagSource); + result.Reset(); + return result; + } + } + + public float retrievalTime; + + [CanBeNull] + public string name; + + [CanBeNull] + public string modHash; + + [CanBeNull] + public string buildId; + + [CanBeNull] + public string serverName; + + [CanBeNull] + public string lobbyName; + + public string lobbyIdStr; + + public ulong? lobbyId; + + public string serverIdStr; + + public ulong? serverId; + + public AddressPortPair? serverAddress; + + public int? ping; + + public string currentSceneName; + + public SceneIndex? currentSceneIndex; + + public DifficultyIndex? currentDifficultyIndex; + + public int? lobbyPlayerCount; + + public int? lobbyMaxPlayers; + + public int? serverPlayerCount; + + public int? serverMaxPlayers; + + public bool? hasPassword; + + [CanBeNull] + public string gameModeName; + + public bool? inGame; + + public bool? joinable; + + public bool? isBlacklisted; + + public bool? isFavorite; + + public bool? didRespond; + + [CanBeNull] + public object userData; + + [CanBeNull] + public GetPlayersDelegate getPlayersImplementation; + + [CanBeNull] + public RequestRefreshDelegate requestRefreshImplementation; + + [CanBeNull] + public GetRuleBookDelegate getRuleBookImplementation; + + public int availableSlots; + + public int availableLobbySlots; + + public int availableServerSlots; + + public int lesserPlayerCount; + + public int greaterPlayerCount; + + public int lesserMaxPlayers; + + public int greaterMaxPlayers; + + [CanBeNull] + public string[] tags { get; private set; } + + public bool IsLobbyIdValid() + { + if (lobbyIdStr == null || !(lobbyIdStr != string.Empty)) + { + return lobbyId.HasValue; + } + return true; + } + + public bool IsServerIdValid() + { + if (serverIdStr == null || !(lobbyIdStr != string.Empty)) + { + return serverId.HasValue; + } + return true; + } + + public void GetPlayers(List output) + { + getPlayersImplementation?.Invoke(in this, output); + } + + public bool GetRuleBook(RuleBook dest) + { + return getRuleBookImplementation?.Invoke(in this, dest) ?? false; + } + + public void RequestRefresh([CanBeNull] RequestRefreshSuccessCallback successCallback, [CanBeNull] Action failureCallback, bool fetchDetails) + { + if (requestRefreshImplementation == null) + { + failureCallback?.Invoke(); + } + else + { + requestRefreshImplementation(in this, successCallback, failureCallback, fetchDetails); + } + } + + public void SetTags(string[] newTags) + { + tags = newTags; + if (tags == null) + { + return; + } + for (int i = 0; i < tags.Length; i++) + { + switch (tags[i]) + { + case "dz": + currentDifficultyIndex = DifficultyIndex.Easy; + break; + case "rs": + currentDifficultyIndex = DifficultyIndex.Normal; + break; + case "mn": + currentDifficultyIndex = DifficultyIndex.Hard; + break; + } + } + } + + public void CalcExtraFields() + { + lesserPlayerCount = int.MinValue; + greaterPlayerCount = int.MaxValue; + lesserMaxPlayers = int.MinValue; + greaterMaxPlayers = int.MaxValue; + Pick(lobbyPlayerCount, ref lesserPlayerCount, ref greaterPlayerCount); + Pick(serverPlayerCount, ref lesserPlayerCount, ref greaterPlayerCount); + Pick(lobbyMaxPlayers, ref lesserMaxPlayers, ref greaterMaxPlayers); + Pick(serverMaxPlayers, ref lesserMaxPlayers, ref greaterMaxPlayers); + if (lesserPlayerCount == int.MinValue) + { + lesserPlayerCount = 0; + } + if (greaterPlayerCount == int.MaxValue) + { + greaterPlayerCount = 0; + } + if (lesserMaxPlayers == int.MinValue) + { + lesserMaxPlayers = 0; + } + if (greaterMaxPlayers == int.MaxValue) + { + greaterMaxPlayers = 0; + } + availableSlots = int.MaxValue; + int? num = lobbyMaxPlayers - lobbyPlayerCount; + int? num2 = serverMaxPlayers - serverPlayerCount; + if (num.HasValue) + { + availableSlots = Math.Min(availableSlots, num.Value); + } + if (num2.HasValue) + { + availableSlots = Math.Min(availableSlots, num2.Value); + } + availableLobbySlots = (lobbyMaxPlayers - lobbyPlayerCount).GetValueOrDefault(); + availableServerSlots = (serverMaxPlayers - serverPlayerCount).GetValueOrDefault(); + if (availableSlots == int.MaxValue) + { + availableSlots = 0; + } + static void Pick(int? inputValue, ref int lesserResult, ref int greaterResult) + { + if (inputValue.HasValue) + { + lesserResult = Math.Max(lesserResult, inputValue.Value); + greaterResult = Math.Min(greaterResult, inputValue.Value); + } + } + } + + public bool HasTag(string tag) + { + if (tags == null) + { + return false; + } + return Array.IndexOf(tags, tag) != -1; + } + + public ArtifactEnumerable GetEnabledArtifacts() + { + ArtifactEnumerable result = new ArtifactEnumerable(""); + if (tags != null) + { + for (int i = 0; i < tags.Length; i++) + { + if (tags[i].StartsWith("a=")) + { + result = new ArtifactEnumerable(tags[i]); + break; + } + } + } + return result; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemotePlayerInfo.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemotePlayerInfo.cs new file mode 100644 index 0000000..12f7faa --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemotePlayerInfo.cs @@ -0,0 +1,8 @@ +namespace RoR2.RemoteGameBrowser; + +public struct RemotePlayerInfo +{ + public string name; + + public ulong id; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteRules.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteRules.cs new file mode 100644 index 0000000..9c707b8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/RemoteRules.cs @@ -0,0 +1,6 @@ +namespace RoR2.RemoteGameBrowser; + +public struct RemoteRules +{ + public RuleBook ruleBook; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SortRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SortRemoteGameProvider.cs new file mode 100644 index 0000000..9f99656 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SortRemoteGameProvider.cs @@ -0,0 +1,216 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace RoR2.RemoteGameBrowser; + +public class SortRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + public delegate int RemoteGameProviderComparison(in RemoteGameInfo a, in RemoteGameInfo b); + + public struct Parameters : IEquatable + { + public int sorterIndex; + + public bool ascending; + + public bool Equals(Parameters other) + { + if (sorterIndex == other.sorterIndex) + { + return ascending == other.ascending; + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is Parameters other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (sorterIndex * 397) ^ ascending.GetHashCode(); + } + } + + public class Sorter + { + public string nameToken; + + public RemoteGameProviderComparison comparer; + } + + private readonly IRemoteGameProvider source; + + private Parameters currentParameters; + + public static Sorter[] sorters = new Sorter[5] + { + new Sorter + { + nameToken = "GAME_BROWSER_SORTER_PING", + comparer = ComparePing + }, + new Sorter + { + nameToken = "GAME_BROWSER_SORTER_NAME", + comparer = CompareName + }, + new Sorter + { + nameToken = "GAME_BROWSER_SORTER_PLAYER_COUNT", + comparer = ComparePlayerCount + }, + new Sorter + { + nameToken = "GAME_BROWSER_SORTER_MAX_PLAYER_COUNT", + comparer = CompareMaxPlayerCount + }, + new Sorter + { + nameToken = "GAME_BROWSER_SORTER_AVAILABLE_SLOTS", + comparer = CompareAvailableSlots + } + }; + + public SortRemoteGameProvider([NotNull] IRemoteGameProvider source) + { + this.source = source; + source.onNewInfoAvailable += OnSourceNewInfoAvailable; + maxTasks = 1; + } + + public override void Dispose() + { + source.onNewInfoAvailable -= OnSourceNewInfoAvailable; + base.Dispose(); + } + + private void OnSourceNewInfoAvailable() + { + SetDirty(); + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + Parameters parameters = GetParameters(); + RemoteGameInfo[] input = source.GetKnownGames(); + RemoteGameInfo[] output = new RemoteGameInfo[input.Length]; + Sorter sorter = sorters[parameters.sorterIndex]; + bool ascending = parameters.ascending; + return new Task(delegate + { + Sort(input, output, sorter, ascending, cancellationToken); + return output; + }); + } + + public override bool RequestRefresh() + { + return source.RequestRefresh(); + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return source.IsBusy(); + } + return true; + } + + private static void Sort(RemoteGameInfo[] input, RemoteGameInfo[] output, Sorter sorter, bool ascending, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + int[] array = new int[input.Length]; + for (int i = 0; i < array.Length; i++) + { + array[i] = i; + } + cancellationToken.ThrowIfCancellationRequested(); + RemoteGameProviderComparison comparer = sorter.comparer; + cancellationToken.ThrowIfCancellationRequested(); + Array.Sort(array, Compare); + cancellationToken.ThrowIfCancellationRequested(); + if (ascending) + { + for (int j = 0; j < array.Length; j++) + { + output[j] = input[array[j]]; + } + } + else + { + for (int k = 0; k < array.Length; k++) + { + output[k] = input[array[array.Length - 1 - k]]; + } + } + int Compare(int indexA, int indexB) + { + return comparer(in input[indexA], in input[indexB]); + } + } + + public Parameters GetParameters() + { + lock (this) + { + return currentParameters; + } + } + + public void SetParameters(Parameters newParameters) + { + if (!currentParameters.Equals(newParameters)) + { + SetParametersInternal(newParameters); + } + } + + private void SetParametersInternal(Parameters newParameters) + { + lock (this) + { + currentParameters = newParameters; + SetDirty(); + } + } + + private static int ComparePing(in RemoteGameInfo a, in RemoteGameInfo b) + { + int num = a.ping ?? int.MinValue; + int value = b.ping ?? int.MinValue; + return num.CompareTo(value); + } + + private static int ComparePlayerCount(in RemoteGameInfo a, in RemoteGameInfo b) + { + return a.lesserPlayerCount.CompareTo(b.lesserPlayerCount); + } + + private static int CompareMaxPlayerCount(in RemoteGameInfo a, in RemoteGameInfo b) + { + return a.lesserPlayerCount.CompareTo(b.lesserPlayerCount); + } + + private static int CompareName(in RemoteGameInfo a, in RemoteGameInfo b) + { + return a.name.CompareTo(b.name); + } + + public static int CompareAvailableSlots(in RemoteGameInfo a, in RemoteGameInfo b) + { + return a.availableSlots.CompareTo(b.availableSlots); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SteamworksLobbyRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SteamworksLobbyRemoteGameProvider.cs new file mode 100644 index 0000000..0f771fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SteamworksLobbyRemoteGameProvider.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Facepunch.Steamworks; +using HG; +using RoR2.Networking; + +namespace RoR2.RemoteGameBrowser; + +public class SteamworksLobbyRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + private readonly List lobbyList = new List(); + + private int waitingForLobbyCount; + + private static readonly char[] tagsSeparator = new char[1] { ',' }; + + private LobbyList.Filter BuildFilter() + { + LobbyList.Filter filter = new LobbyList.Filter(); + if (!searchFilters.allowMismatchedMods) + { + filter.StringFilters.Add("_mh", NetworkModCompatibilityHelper.networkModHash); + } + return filter; + } + + public override bool RequestRefresh() + { + LobbyList.Filter filter = BuildFilter(); + bool num = (PlatformSystems.lobbyManager as SteamworksLobbyManager).RequestLobbyList(this, filter, OnLobbyListReceived); + if (num) + { + waitingForLobbyCount++; + } + return num; + } + + private void OnLobbyListReceived(List lobbies) + { + if (base.disposed) + { + return; + } + waitingForLobbyCount--; + lock (lobbyList) + { + lobbyList.Clear(); + lobbyList.AddRange(lobbies); + SetDirty(); + } + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + LobbyList.Lobby[] lobbies; + lock (lobbyList) + { + lobbies = lobbyList.ToArray(); + } + return new Task(delegate + { + RemoteGameInfo[] array = new RemoteGameInfo[lobbies.Length]; + for (int i = 0; i < lobbies.Length; i++) + { + CreateRemoteGameInfo(lobbies[i], out array[i]); + } + return array; + }, cancellationToken); + } + + private static void CreateRemoteGameInfo(LobbyList.Lobby lobby, out RemoteGameInfo result) + { + result = default(RemoteGameInfo); + result.name = lobby.Name; + result.lobbyName = lobby.Name; + result.lobbyId = lobby.LobbyID; + string text = GetString("_map"); + result.serverId = GetULong("server_id"); + result.serverAddress = GetAddressPortPair("server_address"); + result.serverName = GetString("_svnm"); + result.lobbyPlayerCount = GetInt("player_count", 1, int.MaxValue) ?? 1; + result.lobbyMaxPlayers = GetInt("total_max_players", 1, int.MaxValue) ?? 1; + result.serverPlayerCount = GetInt("_svplc", 0, int.MaxValue); + result.serverMaxPlayers = GetInt("_svmpl", 0, int.MaxValue); + result.inGame = result.serverId.HasValue || result.serverAddress.HasValue; + result.currentSceneName = text; + if (text != null) + { + result.currentSceneIndex = SceneCatalog.GetSceneDefFromSceneName(text)?.sceneDefIndex; + } + result.requestRefreshImplementation = RemoteGameInfoRequestRefresh; + result.getPlayersImplementation = RemoteGameInfoGetPlayers; + result.getRuleBookImplementation = RemoteGameInfoGetRuleBook; + result.userData = lobby; + result.hasPassword = GetBool("_pw"); + result.gameModeName = GetString("_svgm"); + result.buildId = GetString("build_id") ?? "UNKNOWN"; + result.modHash = GetString("_mh") ?? "UNKNOWN"; + result.SetTags(GetTags("_svtags")); + result.CalcExtraFields(); + AddressPortPair? GetAddressPortPair(string key) + { + if (!AddressPortPair.TryParse(GetString(key), out var addressPortPair)) + { + return null; + } + return addressPortPair; + } + bool? GetBool(string key) + { + return GetInt(key, int.MinValue, int.MaxValue) > 0; + } + int? GetInt(string key, int min, int max) + { + if (int.TryParse(GetString(key), out var result2) && min <= result2 && result2 <= max) + { + return result2; + } + return null; + } + string GetString(string key) + { + string data = lobby.GetData(key); + if (!(data == string.Empty)) + { + return data; + } + return null; + } + string[] GetTags(string key) + { + return GetString(key)?.Split(tagsSeparator, StringSplitOptions.None); + } + ulong? GetULong(string key) + { + if (!ulong.TryParse(GetString(key), out var result3)) + { + return null; + } + return result3; + } + } + + private static void RemoteGameInfoRequestRefresh(in RemoteGameInfo remoteGameInfo, RemoteGameInfo.RequestRefreshSuccessCallback successCallback, Action failureCallback, bool fetchDetails) + { + if (!(remoteGameInfo.userData is LobbyList.Lobby lobby)) + { + return; + } + Task lobby2 = Client.Instance.LobbyList.GetLobby(lobby.LobbyID); + if (lobby2 == null) + { + failureCallback?.Invoke(); + return; + } + lobby2.ContinueWith(delegate(Task antecedentTask) + { + RoR2Application.onNextUpdate += delegate + { + HandleRefresh(antecedentTask); + }; + }); + void HandleRefresh(Task antecedentTask) + { + LobbyList.Lobby result = antecedentTask.Result; + if (result == null) + { + failureCallback?.Invoke(); + } + else + { + CreateRemoteGameInfo(result, out var result2); + successCallback?.Invoke(in result2); + } + } + } + + private static bool RemoteGameInfoGetRuleBook(in RemoteGameInfo remoteGameInfo, RuleBook dest) + { + if (remoteGameInfo.userData is LobbyList.Lobby lobby) + { + KeyValueUnsplitter keyValueUnsplitter = new KeyValueUnsplitter("rulebook"); + List> list = CollectionPool, List>>.RentCollection(); + try + { + int i = 0; + for (int dataCount = lobby.GetDataCount(); i < dataCount; i++) + { + if (lobby.GetDataByIndex(i, out var key, out var value)) + { + list.Add(new KeyValuePair(key, value)); + } + } + string value2 = keyValueUnsplitter.GetValue(list); + if (!string.IsNullOrEmpty(value2)) + { + RuleBook.ReadBase64(value2, dest); + return true; + } + } + finally + { + list = CollectionPool, List>>.ReturnCollection(list); + } + } + return false; + } + + private static void RemoteGameInfoGetPlayers(in RemoteGameInfo remoteGameInfo, List output) + { + if (remoteGameInfo.userData is LobbyList.Lobby lobby) + { + for (int i = 0; i < lobby.NumMembers; i++) + { + output.Add(new RemotePlayerInfo + { + id = 0uL, + name = "???" + }); + } + } + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return waitingForLobbyCount > 0; + } + return true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SteamworksServerRemoteGameProvider.cs b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SteamworksServerRemoteGameProvider.cs new file mode 100644 index 0000000..ecfa32b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.RemoteGameBrowser/SteamworksServerRemoteGameProvider.cs @@ -0,0 +1,462 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Facepunch.Steamworks; +using RoR2.Networking; + +namespace RoR2.RemoteGameBrowser; + +public class SteamworksServerRemoteGameProvider : BaseAsyncRemoteGameProvider +{ + public new struct SearchFilters : IEquatable + { + public bool allowDedicatedServers; + + public bool allowListenServers; + + public bool mustHavePlayers; + + public bool mustNotBeFull; + + public bool allowInProgressGames; + + public bool allowMismatchedMods; + + public string requiredTags; + + public string forbiddenTags; + + public bool Equals(SearchFilters other) + { + if (allowDedicatedServers == other.allowDedicatedServers && allowListenServers == other.allowListenServers && mustHavePlayers == other.mustHavePlayers && mustNotBeFull == other.mustNotBeFull && allowInProgressGames == other.allowInProgressGames && allowMismatchedMods == other.allowMismatchedMods && string.Equals(requiredTags, other.requiredTags)) + { + return string.Equals(forbiddenTags, other.forbiddenTags); + } + return false; + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (obj is SearchFilters other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return (((((((((((((allowDedicatedServers.GetHashCode() * 397) ^ allowListenServers.GetHashCode()) * 397) ^ mustHavePlayers.GetHashCode()) * 397) ^ mustNotBeFull.GetHashCode()) * 397) ^ allowInProgressGames.GetHashCode()) * 397) ^ allowMismatchedMods.GetHashCode()) * 397) ^ ((requiredTags != null) ? requiredTags.GetHashCode() : 0)) * 397) ^ ((forbiddenTags != null) ? forbiddenTags.GetHashCode() : 0); + } + } + + public enum Mode + { + Internet, + Favorites, + History, + Local, + Friends + } + + private struct FilterElement + { + public string key; + + public string value; + + public int operandCount; + + public bool isOperator; + } + + private Mode mode; + + private ServerList.Filter filter; + + private ServerList.Request currentRequest; + + public new bool refreshOnFiltersChanged; + + private static readonly int k_cbMaxGameServerGameData = 2048; + + private static readonly int k_cbMaxGameServerGameDescription = 64; + + private static readonly int k_cbMaxGameServerGameDir = 32; + + private static readonly int k_cbMaxGameServerMapName = 32; + + private static readonly int k_cbMaxGameServerName = 64; + + private static readonly int k_cbMaxGameServerTags = 128; + + private new SearchFilters searchFilters; + + public SteamworksServerRemoteGameProvider(Mode mode) + { + this.mode = mode; + filter = new ServerList.Filter(); + } + + public new SearchFilters GetSearchFilters() + { + return searchFilters; + } + + public void SetSearchFilters(SearchFilters newSearchFilters) + { + if (!searchFilters.Equals(newSearchFilters)) + { + searchFilters = newSearchFilters; + BuildFilter(); + if (refreshOnFiltersChanged) + { + RequestRefresh(); + } + SetDirty(); + } + } + + private void BuildFilter() + { + filter.Clear(); + FilterElement[] elements = new FilterElement[64]; + int elementCount = 0; + Stack<(int, int)> operatorIndicesAndCounts = new Stack<(int, int)>(); + int currentOperandCount = 0; + PushOperation("and"); + AddOperand("appid", Client.Instance.AppId.ToString()); + if (searchFilters.allowDedicatedServers != searchFilters.allowListenServers) + { + if (searchFilters.allowListenServers) + { + PushOperation("nor"); + AddOperand("dedicated", ""); + PopOperation(); + } + else + { + AddOperand("dedicated", ""); + } + } + if (searchFilters.mustHavePlayers) + { + AddOperand("hasplayers", ""); + } + if (searchFilters.mustNotBeFull) + { + AddOperand("notfull", ""); + } + if (!searchFilters.allowInProgressGames) + { + AddOperand("map", "lobby"); + } + if (!string.IsNullOrEmpty(searchFilters.requiredTags)) + { + AddOperand("gametagsand", searchFilters.requiredTags); + } + if (!string.IsNullOrEmpty(searchFilters.forbiddenTags)) + { + AddOperand("gametagsnor", searchFilters.forbiddenTags); + } + AddOperand("gamedataand", ServerManagerBase.GetVersionGameDataString()); + if (!searchFilters.allowMismatchedMods) + { + AddOperand("gamedataand", NetworkModCompatibilityHelper.steamworksGameserverGameDataValue); + } + PopOperation(); + for (int j = 0; j < elementCount; j++) + { + ref FilterElement reference = ref elements[j]; + filter.Add(reference.key, reference.isOperator ? reference.operandCount.ToString() : reference.value); + } + void AddOperand(string key, string value) + { + int num2 = currentOperandCount + 1; + currentOperandCount = num2; + GetElement(elementCount++) = new FilterElement + { + key = key, + value = value, + isOperator = false + }; + } + ref FilterElement GetElement(int i) + { + if (elements.Length < i) + { + Array.Resize(ref elements, elements.Length * 2); + } + return ref elements[i]; + } + void PopOperation() + { + int num = currentOperandCount; + int i2; + (i2, currentOperandCount) = operatorIndicesAndCounts.Pop(); + currentOperandCount += num; + GetElement(i2).operandCount = num; + } + void PushOperation(string operationCode) + { + int num3 = currentOperandCount + 1; + currentOperandCount = num3; + int num4 = elementCount++; + GetElement(num4) = new FilterElement + { + key = operationCode, + isOperator = true + }; + operatorIndicesAndCounts.Push((num4, currentOperandCount)); + currentOperandCount = 0; + } + } + + public override bool RequestRefresh() + { + CancelCurrentRequest(); + currentRequest = CreateRequest(mode, filter); + currentRequest.OnUpdate = OnCurrentRequestUpdated; + currentRequest.OnFinished = OnCurrentRequestFinished; + currentRequest.OnServerResponded = OnCurrentRequestServerResponded; + return true; + } + + private static Func GetRequestMethod(Mode mode) + { + ServerList serverList = Client.Instance.ServerList; + return mode switch + { + Mode.Internet => serverList.Internet, + Mode.Favorites => serverList.Favourites, + Mode.History => serverList.History, + Mode.Local => serverList.Local, + Mode.Friends => serverList.Friends, + _ => throw new ArgumentOutOfRangeException(), + }; + } + + private static ServerList.Request CreateRequest(Mode mode, ServerList.Filter filter) + { + return GetRequestMethod(mode)(filter); + } + + private void OnCurrentRequestServerResponded(ServerList.Server server) + { + SetDirty(); + } + + private void OnCurrentRequestFinished() + { + SetDirty(); + } + + private void OnCurrentRequestUpdated() + { + SetDirty(); + } + + private void CancelCurrentRequest() + { + if (currentRequest != null) + { + currentRequest.OnFinished = null; + currentRequest.OnServerResponded = null; + currentRequest.OnUpdate = null; + currentRequest.Dispose(); + currentRequest = null; + } + } + + private static RemoteGameInfo[] GenerateRemoteGameInfoCache(ServerList.Server[] knownServers, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + RemoteGameInfo[] array = new RemoteGameInfo[knownServers.Length]; + for (int i = 0; i < knownServers.Length; i++) + { + cancellationToken.ThrowIfCancellationRequested(); + ServerList.Server serverInfo = knownServers[i]; + GenerateRemoteGameInfo(ref array[i], serverInfo); + } + return array; + } + + protected override Task CreateTask(CancellationToken cancellationToken) + { + if (currentRequest == null) + { + return new Task(() => Array.Empty()); + } + ServerList.Server[] servers = currentRequest.Responded.ToArray(); + return new Task(() => GenerateRemoteGameInfoCache(servers, cancellationToken), cancellationToken); + } + + public override void Dispose() + { + CancelCurrentRequest(); + base.Dispose(); + } + + public override bool IsBusy() + { + if (!base.IsBusy()) + { + return !(currentRequest?.Finished ?? true); + } + return true; + } + + private static void GenerateRemoteGameInfo(ref RemoteGameInfo remoteGameInfo, ServerList.Server serverInfo) + { + remoteGameInfo.name = serverInfo.Name; + remoteGameInfo.serverAddress = new AddressPortPair(serverInfo.Address, (ushort)serverInfo.ConnectionPort); + remoteGameInfo.serverName = serverInfo.Name; + remoteGameInfo.serverId = serverInfo.SteamId; + remoteGameInfo.hasPassword = serverInfo.Passworded; + remoteGameInfo.serverPlayerCount = serverInfo.Players; + remoteGameInfo.serverMaxPlayers = serverInfo.MaxPlayers; + remoteGameInfo.ping = serverInfo.Ping; + remoteGameInfo.SetTags(serverInfo.Tags); + remoteGameInfo.isFavorite = serverInfo.Favourite; + remoteGameInfo.userData = serverInfo; + remoteGameInfo.getPlayersImplementation = RemoteGameInfoGetPlayers; + remoteGameInfo.requestRefreshImplementation = RemoteGameInfoRequestRefresh; + remoteGameInfo.getRuleBookImplementation = RemoteGameInfoGetRuleBook; + remoteGameInfo.currentSceneName = serverInfo.Map; + remoteGameInfo.currentSceneIndex = SceneCatalog.GetSceneDefFromSceneName(serverInfo.Map)?.sceneDefIndex; + remoteGameInfo.CalcExtraFields(); + } + + private static void RemoteGameInfoRequestRefresh(in RemoteGameInfo remoteGameInfo, RemoteGameInfo.RequestRefreshSuccessCallback successCallback, Action failureCallback, bool fetchDetails) + { + if (remoteGameInfo.userData is ServerList.Server) + { + ServerList.Filter filter = new ServerList.Filter(); + filter.Add("and", "2"); + filter.Add("appid", Client.Instance.AppId.ToString()); + filter.Add("gameaddr", remoteGameInfo.serverAddress.ToString()); + ServerList.Request lanRefreshRequest = CreateRequest(Mode.Local, filter); + lanRefreshRequest.OnFinished = delegate + { + ServerList.Server refreshedServerInfoFromRequest = GetRefreshedServerInfoFromRequest(lanRefreshRequest); + if (refreshedServerInfoFromRequest != null) + { + HandleNewInfo(refreshedServerInfoFromRequest); + } + else + { + ServerList.Request internetRefreshRequest = CreateRequest(Mode.Internet, filter); + internetRefreshRequest.OnFinished = delegate + { + ServerList.Server refreshedServerInfoFromRequest2 = GetRefreshedServerInfoFromRequest(internetRefreshRequest); + if (refreshedServerInfoFromRequest2 != null) + { + HandleNewInfo(refreshedServerInfoFromRequest2); + } + else + { + failureCallback?.Invoke(); + } + }; + } + }; + } + else + { + failureCallback?.Invoke(); + } + static ServerList.Server GetRefreshedServerInfoFromRequest(ServerList.Request request) + { + if (request.Responded.Count > 0) + { + return request.Responded[0]; + } + if (request.Unresponsive.Count > 0) + { + return request.Unresponsive[0]; + } + return null; + } + void HandleNewInfo(ServerList.Server refreshedServerInfo) + { + RemoteGameInfo result = default(RemoteGameInfo); + GenerateRemoteGameInfo(ref result, refreshedServerInfo); + int awaitingRequests; + if (fetchDetails) + { + awaitingRequests = 2; + ServerList.Server server = refreshedServerInfo; + server.OnReceivedPlayerInfos = (Action)Delegate.Combine(server.OnReceivedPlayerInfos, new Action(OnReceivedPlayerInfos)); + ServerList.Server server2 = refreshedServerInfo; + server2.OnReceivedRules = (Action)Delegate.Combine(server2.OnReceivedRules, new Action(OnReceivedRules)); + refreshedServerInfo.FetchPlayerInfos(); + refreshedServerInfo.FetchRules(); + } + else + { + successCallback?.Invoke(in result); + } + void OnReceivedPlayerInfos(bool success) + { + ServerList.Server server4 = refreshedServerInfo; + server4.OnReceivedPlayerInfos = (Action)Delegate.Remove(server4.OnReceivedPlayerInfos, new Action(OnReceivedPlayerInfos)); + int num2 = awaitingRequests - 1; + awaitingRequests = num2; + TryComplete(); + } + void OnReceivedRules(bool success) + { + ServerList.Server server3 = refreshedServerInfo; + server3.OnReceivedRules = (Action)Delegate.Remove(server3.OnReceivedRules, new Action(OnReceivedRules)); + if (success && refreshedServerInfo.HasRules) + { + refreshedServerInfo.Rules.TryGetValue("gameMode", out result.gameModeName); + refreshedServerInfo.Rules.TryGetValue("buildId", out result.buildId); + refreshedServerInfo.Rules.TryGetValue("modHash", out result.modHash); + result.buildId = result.buildId ?? "UNKNOWN"; + result.modHash = result.modHash ?? "UNKNOWN"; + } + int num = awaitingRequests - 1; + awaitingRequests = num; + TryComplete(); + } + void TryComplete() + { + if (awaitingRequests == 0) + { + successCallback?.Invoke(in result); + } + } + } + } + + private static bool RemoteGameInfoGetRuleBook(in RemoteGameInfo remoteGameInfo, RuleBook dest) + { + if (remoteGameInfo.userData is ServerList.Server { HasRules: not false } server) + { + dest.SetToDefaults(); + RuleBook.ReadBase64(new KeyValueUnsplitter("ruleBook").GetValue(server.Rules), dest); + return true; + } + return false; + } + + private static void RemoteGameInfoGetPlayers(in RemoteGameInfo remoteGameInfo, List output) + { + if (remoteGameInfo.userData is ServerList.Server { PlayerInfos: { } playerInfos }) + { + for (int i = 0; i < playerInfos.Count; i++) + { + output.Add(new RemotePlayerInfo + { + name = playerInfos[i].name + }); + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Scripts.GameBehaviors.UI/ObjectiveStripAnimationParam.cs b/ilspy_dump/ror2_csproj/RoR2.Scripts.GameBehaviors.UI/ObjectiveStripAnimationParam.cs new file mode 100644 index 0000000..ec43e0a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Scripts.GameBehaviors.UI/ObjectiveStripAnimationParam.cs @@ -0,0 +1,11 @@ +using System; + +namespace RoR2.Scripts.GameBehaviors.UI; + +[Serializable] +public struct ObjectiveStripAnimationParam +{ + public string Param; + + public float Value; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Scripts.GameBehaviors.UI/ObjectiveStripAnimationParams.cs b/ilspy_dump/ror2_csproj/RoR2.Scripts.GameBehaviors.UI/ObjectiveStripAnimationParams.cs new file mode 100644 index 0000000..9f98738 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Scripts.GameBehaviors.UI/ObjectiveStripAnimationParams.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace RoR2.Scripts.GameBehaviors.UI; + +public class ObjectiveStripAnimationParams : MonoBehaviour +{ + [SerializeField] + protected List Params; + + public float GetParam(string ParamName, float defaultValue) + { + int num = Params.FindIndex((ObjectiveStripAnimationParam objectiveStripAnimationParam) => objectiveStripAnimationParam.Param == ParamName); + if (num >= 0) + { + return Params[num].Value; + } + return defaultValue; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialFirstLevelEventGate.cs b/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialFirstLevelEventGate.cs new file mode 100644 index 0000000..a320a71 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialFirstLevelEventGate.cs @@ -0,0 +1,23 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.Scripts.Tutorial; + +public class TutorialFirstLevelEventGate : MonoBehaviour +{ + public UnityEvent ExecTutorialIsEnabled; + + public UnityEvent ExecTutorialIsDisabled; + + public void Exec() + { + if (TutorialManager.isTutorialEnabled && (bool)Run.instance && Run.instance.stageClearCount == 0) + { + ExecTutorialIsEnabled?.Invoke(); + } + else + { + ExecTutorialIsDisabled?.Invoke(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialObjectiveCrossfadeHelper.cs b/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialObjectiveCrossfadeHelper.cs new file mode 100644 index 0000000..965ffcc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialObjectiveCrossfadeHelper.cs @@ -0,0 +1,18 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.Scripts.Tutorial; + +public class TutorialObjectiveCrossfadeHelper : MonoBehaviour +{ + public UnityEvent OnBeginFinishCrossfade; + + public Action FinishCrossfadeAction { get; set; } + + public void FinishCrossfade() + { + FinishCrossfadeAction?.Invoke(); + OnBeginFinishCrossfade?.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialObjectiveHelper.cs b/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialObjectiveHelper.cs new file mode 100644 index 0000000..983e5c4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Scripts.Tutorial/TutorialObjectiveHelper.cs @@ -0,0 +1,44 @@ +using RoR2.UI; +using UnityEngine; + +namespace RoR2.Scripts.Tutorial; + +public class TutorialObjectiveHelper : MonoBehaviour +{ + public GameObject SearchRoot; + + public HGTextMeshProUGUI TextToUpdate; + + private ObjectivePanelController _objectivePanelController; + + private TutorialObjectiveCrossfadeHelper _crossfadeHelper; + + private void Start() + { + if ((bool)SearchRoot) + { + ObjectivePanelController componentInChildren = SearchRoot.GetComponentInChildren(); + if ((object)componentInChildren != null) + { + _objectivePanelController = componentInChildren; + } + } + } + + public void GrabText() + { + if ((bool)_objectivePanelController && _objectivePanelController.GetPrimaryObjectiveTracker(out var primaryObjectiveTracker)) + { + TextToUpdate.text = primaryObjectiveTracker.GetString(); + _crossfadeHelper = primaryObjectiveTracker.stripObject.GetComponent(); + } + } + + public void TriggerObjectiveSideCrossfade() + { + if ((bool)_crossfadeHelper) + { + _crossfadeHelper.FinishCrossfade(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Scripts.Utility/ScopedReset.cs b/ilspy_dump/ror2_csproj/RoR2.Scripts.Utility/ScopedReset.cs new file mode 100644 index 0000000..858919d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Scripts.Utility/ScopedReset.cs @@ -0,0 +1,22 @@ +using System; + +namespace RoR2.Scripts.Utility; + +internal class ScopedReset : IDisposable +{ + private T originalValue; + + private Action _setter; + + public ScopedReset(Func getter, Action setter, T tempVal) + { + originalValue = getter(); + setter(tempVal); + _setter = setter; + } + + public void Dispose() + { + _setter(originalValue); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/CaptainOrbitalSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/CaptainOrbitalSkillDef.cs new file mode 100644 index 0000000..a955267 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/CaptainOrbitalSkillDef.cs @@ -0,0 +1,59 @@ +using UnityEngine; + +namespace RoR2.Skills; + +public class CaptainOrbitalSkillDef : SkillDef +{ + public Sprite disabledIcon; + + public string disabledNameToken; + + public string disabledDescriptionToken; + + private bool isAvailable => !SceneCatalog.mostRecentSceneDef.blockOrbitalSkills; + + public override Sprite GetCurrentIcon(GenericSkill skillSlot) + { + if (!isAvailable) + { + return disabledIcon; + } + return base.GetCurrentIcon(skillSlot); + } + + public override string GetCurrentNameToken(GenericSkill skillSlot) + { + if (!isAvailable) + { + return disabledNameToken; + } + return base.GetCurrentNameToken(skillSlot); + } + + public override string GetCurrentDescriptionToken(GenericSkill skillSlot) + { + if (!isAvailable) + { + return disabledDescriptionToken; + } + return base.GetCurrentDescriptionToken(skillSlot); + } + + public override bool CanExecute(GenericSkill skillSlot) + { + if (isAvailable) + { + return base.CanExecute(skillSlot); + } + return false; + } + + public override bool IsReady(GenericSkill skillSlot) + { + if (isAvailable) + { + return base.IsReady(skillSlot); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/CaptainSupplyDropSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/CaptainSupplyDropSkillDef.cs new file mode 100644 index 0000000..fded8f5 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/CaptainSupplyDropSkillDef.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using HG; +using UnityEngine; + +namespace RoR2.Skills; + +public class CaptainSupplyDropSkillDef : CaptainOrbitalSkillDef +{ + protected class InstanceData : BaseSkillInstanceData, IDisposable + { + public List supplySkillSlots; + + public bool anySupplyDropsAvailable; + + private GenericSkill skillSlot; + + private string[] supplyDropSkillSlotNames; + + public InstanceData(GenericSkill skillSlot, string[] supplyDropSkillSlotNames) + { + supplySkillSlots = CollectionPool>.RentCollection(); + this.skillSlot = skillSlot; + this.supplyDropSkillSlotNames = supplyDropSkillSlotNames; + } + + public void Dispose() + { + supplySkillSlots = CollectionPool>.ReturnCollection(supplySkillSlots); + skillSlot = null; + supplyDropSkillSlotNames = null; + } + + private bool CheckForSupplyDropAvailable() + { + for (int i = 0; i < supplySkillSlots.Count; i++) + { + if (supplySkillSlots[i].IsReady()) + { + return true; + } + } + return false; + } + + private void FindSupplyDropSkillSlots() + { + for (int i = 0; i < supplyDropSkillSlotNames.Length; i++) + { + GenericSkill genericSkill = skillSlot.GetComponent().FindSkill(supplyDropSkillSlotNames[i]); + if ((bool)genericSkill) + { + supplySkillSlots.Add(genericSkill); + } + } + } + + public void FixedUpdate() + { + if (supplySkillSlots.Count == 0) + { + FindSupplyDropSkillSlots(); + } + anySupplyDropsAvailable = CheckForSupplyDropAvailable(); + } + } + + public string[] supplyDropSkillSlotNames = Array.Empty(); + + public Sprite exhaustedIcon; + + public string exhaustedNameToken; + + public string exhaustedDescriptionToken; + + public override Sprite GetCurrentIcon(GenericSkill skillSlot) + { + if (!((InstanceData)skillSlot.skillInstanceData).anySupplyDropsAvailable) + { + return exhaustedIcon; + } + return base.GetCurrentIcon(skillSlot); + } + + public override string GetCurrentNameToken(GenericSkill skillSlot) + { + if (!((InstanceData)skillSlot.skillInstanceData).anySupplyDropsAvailable) + { + return exhaustedNameToken; + } + return base.GetCurrentNameToken(skillSlot); + } + + public override string GetCurrentDescriptionToken(GenericSkill skillSlot) + { + if (!((InstanceData)skillSlot.skillInstanceData).anySupplyDropsAvailable) + { + return exhaustedDescriptionToken; + } + return base.GetCurrentDescriptionToken(skillSlot); + } + + public override bool CanExecute(GenericSkill skillSlot) + { + if (((InstanceData)skillSlot.skillInstanceData).anySupplyDropsAvailable) + { + return base.CanExecute(skillSlot); + } + return false; + } + + public override bool IsReady(GenericSkill skillSlot) + { + if (((InstanceData)skillSlot.skillInstanceData).anySupplyDropsAvailable) + { + return base.IsReady(skillSlot); + } + return false; + } + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + return new InstanceData(skillSlot, supplyDropSkillSlotNames); + } + + public override void OnUnassigned(GenericSkill skillSlot) + { + ((InstanceData)skillSlot.skillInstanceData).Dispose(); + base.OnUnassigned(skillSlot); + } + + public override void OnFixedUpdate(GenericSkill skillSlot, float deltaTime) + { + base.OnFixedUpdate(skillSlot, deltaTime); + ((InstanceData)skillSlot.skillInstanceData).FixedUpdate(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/ComboSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/ComboSkillDef.cs new file mode 100644 index 0000000..c1b590b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/ComboSkillDef.cs @@ -0,0 +1,43 @@ +using System; +using EntityStates; +using HG; + +namespace RoR2.Skills; + +public class ComboSkillDef : SkillDef +{ + [Serializable] + public struct Combo + { + public SerializableEntityStateType activationStateType; + } + + protected class InstanceData : BaseSkillInstanceData + { + public int comboCounter; + } + + public Combo[] comboList; + + protected SerializableEntityStateType GetNextStateType(GenericSkill skillSlot) + { + return ArrayUtils.GetSafe(comboList, ((InstanceData)skillSlot.skillInstanceData).comboCounter).activationStateType; + } + + protected override EntityState InstantiateNextState(GenericSkill skillSlot) + { + SerializableEntityStateType serializableStateType = GetNextStateType(skillSlot); + return EntityStateCatalog.InstantiateState(ref serializableStateType); + } + + public override void OnExecute(GenericSkill skillSlot) + { + base.OnExecute(skillSlot); + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + instanceData.comboCounter++; + if (instanceData.comboCounter >= comboList.Length) + { + instanceData.comboCounter = 0; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/ConditionalSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/ConditionalSkillDef.cs new file mode 100644 index 0000000..9dee679 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/ConditionalSkillDef.cs @@ -0,0 +1,61 @@ +using EntityStates; +using JetBrains.Annotations; + +namespace RoR2.Skills; + +public class ConditionalSkillDef : SkillDef +{ + protected class InstanceData : BaseSkillInstanceData + { + public CharacterBody characterBody; + } + + public SerializableEntityStateType baseStateType; + + public SerializableEntityStateType sprintStateType; + + public SerializableEntityStateType jumpStateType; + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData + { + characterBody = skillSlot.GetComponent() + }; + } + + public bool IsGrounded([NotNull] GenericSkill skillSlot) + { + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if ((bool)instanceData.characterBody.characterMotor && instanceData.characterBody.characterMotor.isGrounded) + { + return true; + } + return false; + } + + public bool IsSprinting([NotNull] GenericSkill skillSlot) + { + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if ((bool)instanceData.characterBody && instanceData.characterBody.isSprinting) + { + return true; + } + return false; + } + + protected override EntityState InstantiateNextState(GenericSkill skillSlot) + { + bool num = IsGrounded(skillSlot); + bool flag = IsSprinting(skillSlot); + if (!num) + { + return EntityStateCatalog.InstantiateState(ref jumpStateType); + } + if (flag) + { + return EntityStateCatalog.InstantiateState(ref sprintStateType); + } + return EntityStateCatalog.InstantiateState(ref baseStateType); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/ConditionalSkillOverride.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/ConditionalSkillOverride.cs new file mode 100644 index 0000000..b254d8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/ConditionalSkillOverride.cs @@ -0,0 +1,74 @@ +using System; +using UnityEngine; + +namespace RoR2.Skills; + +public class ConditionalSkillOverride : MonoBehaviour +{ + [Serializable] + public struct ConditionalSkillInfo + { + public GenericSkill skillSlot; + + public SkillDef sprintSkillDef; + + public SkillDef airborneSkillDef; + } + + public CharacterBody characterBody; + + public ConditionalSkillInfo[] conditionalSkillInfos; + + private bool wasSprinting; + + private bool wasAirborne; + + private void Start() + { + } + + private void FixedUpdate() + { + bool flag = false; + bool flag2 = false; + if ((bool)characterBody) + { + flag = characterBody.isSprinting; + if ((bool)characterBody.characterMotor) + { + flag2 = characterBody.characterMotor.isGrounded; + } + } + bool flag3 = wasSprinting || wasAirborne; + bool flag4 = flag || flag2; + ConditionalSkillInfo[] array = conditionalSkillInfos; + for (int i = 0; i < array.Length; i++) + { + ConditionalSkillInfo conditionalSkillInfo = array[i]; + if (flag3) + { + if (wasAirborne && !flag2) + { + conditionalSkillInfo.skillSlot.UnsetSkillOverride(this, conditionalSkillInfo.airborneSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + else if (wasSprinting && !flag) + { + conditionalSkillInfo.skillSlot.UnsetSkillOverride(this, conditionalSkillInfo.sprintSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + } + if (flag4) + { + if (flag2 && !wasAirborne) + { + conditionalSkillInfo.skillSlot.SetSkillOverride(this, conditionalSkillInfo.airborneSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + else if (flag && !wasSprinting) + { + conditionalSkillInfo.skillSlot.SetSkillOverride(this, conditionalSkillInfo.sprintSkillDef, GenericSkill.SkillOverridePriority.Contextual); + } + } + } + wasAirborne = flag2; + wasSprinting = flag; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/EngiMineDeployerSkill.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/EngiMineDeployerSkill.cs new file mode 100644 index 0000000..24180ca --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/EngiMineDeployerSkill.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using EntityStates.Engi.MineDeployer; + +namespace RoR2.Skills; + +public class EngiMineDeployerSkill : SkillDef +{ + public override bool CanExecute(GenericSkill skillSlot) + { + List instancesList = BaseMineDeployerState.instancesList; + for (int i = 0; i < instancesList.Count; i++) + { + if (instancesList[i].owner == skillSlot.gameObject) + { + return false; + } + } + return base.CanExecute(skillSlot); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/GroundedSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/GroundedSkillDef.cs new file mode 100644 index 0000000..c3e1d56 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/GroundedSkillDef.cs @@ -0,0 +1,38 @@ +using JetBrains.Annotations; + +namespace RoR2.Skills; + +public class GroundedSkillDef : SkillDef +{ + protected class InstanceData : BaseSkillInstanceData + { + public CharacterMotor characterMotor; + } + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData + { + characterMotor = skillSlot.GetComponent() + }; + } + + public bool IsGrounded([NotNull] GenericSkill skillSlot) + { + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if ((bool)instanceData.characterMotor && instanceData.characterMotor.isGrounded) + { + return true; + } + return false; + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (HasRequiredStockAndDelay(skillSlot)) + { + return IsGrounded(skillSlot); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/HuntressTrackingSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/HuntressTrackingSkillDef.cs new file mode 100644 index 0000000..f78538b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/HuntressTrackingSkillDef.cs @@ -0,0 +1,48 @@ +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/HuntressTrackingSkillDef")] +public class HuntressTrackingSkillDef : SkillDef +{ + protected class InstanceData : BaseSkillInstanceData + { + public HuntressTracker huntressTracker; + } + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData + { + huntressTracker = skillSlot.GetComponent() + }; + } + + private static bool HasTarget([NotNull] GenericSkill skillSlot) + { + if (!(((InstanceData)skillSlot.skillInstanceData).huntressTracker?.GetTrackingTarget())) + { + return false; + } + return true; + } + + public override bool CanExecute([NotNull] GenericSkill skillSlot) + { + if (!HasTarget(skillSlot)) + { + return false; + } + return base.CanExecute(skillSlot); + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (base.IsReady(skillSlot)) + { + return HasTarget(skillSlot); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/LunarDetonatorSkill.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/LunarDetonatorSkill.cs new file mode 100644 index 0000000..cc25d0f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/LunarDetonatorSkill.cs @@ -0,0 +1,86 @@ +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.ResourceManagement.AsyncOperations; + +namespace RoR2.Skills; + +public class LunarDetonatorSkill : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + private GenericSkill _skillSlot; + + private LunarDetonatorPassiveAttachment lunarDetonatorPassiveAttachment; + + public GenericSkill skillSlot + { + get + { + return _skillSlot; + } + set + { + if ((object)_skillSlot == value) + { + return; + } + if ((object)_skillSlot != null) + { + _skillSlot.characterBody.onInventoryChanged -= OnInventoryChanged; + } + if ((bool)lunarDetonatorPassiveAttachment) + { + Object.Destroy(lunarDetonatorPassiveAttachment.gameObject); + } + lunarDetonatorPassiveAttachment = null; + _skillSlot = value; + if ((object)_skillSlot != null) + { + _skillSlot.characterBody.onInventoryChanged += OnInventoryChanged; + if (NetworkServer.active && (bool)_skillSlot.characterBody) + { + GameObject gameObject = Object.Instantiate(lunarDetonatorPassiveAttachmentPrefab); + lunarDetonatorPassiveAttachment = gameObject.GetComponent(); + lunarDetonatorPassiveAttachment.monitoredSkill = skillSlot; + gameObject.GetComponent().AttachToGameObjectAndSpawn(_skillSlot.characterBody.gameObject); + } + } + } + } + + public void OnInventoryChanged() + { + skillSlot.RecalculateValues(); + } + } + + private static GameObject lunarDetonatorPassiveAttachmentPrefab; + + [InitDuringStartup] + private static void Init() + { + AsyncOperationHandle asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/NetworkedObjects/BodyAttachments/LunarDetonatorPassiveAttachment"); + asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) + { + lunarDetonatorPassiveAttachmentPrefab = x.Result; + }; + } + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + return new InstanceData + { + skillSlot = skillSlot + }; + } + + public override void OnUnassigned(GenericSkill skillSlot) + { + ((InstanceData)skillSlot.skillInstanceData).skillSlot = null; + } + + public override float GetRechargeInterval(GenericSkill skillSlot) + { + return (float)skillSlot.characterBody.inventory.GetItemCount(RoR2Content.Items.LunarSpecialReplacement) * baseRechargeInterval; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/LunarPrimaryReplacementSkill.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/LunarPrimaryReplacementSkill.cs new file mode 100644 index 0000000..d85316a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/LunarPrimaryReplacementSkill.cs @@ -0,0 +1,42 @@ +namespace RoR2.Skills; + +public class LunarPrimaryReplacementSkill : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public GenericSkill skillSlot; + + public void OnInventoryChanged() + { + skillSlot.RecalculateValues(); + } + } + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + InstanceData instanceData = new InstanceData(); + instanceData.skillSlot = skillSlot; + skillSlot.characterBody.onInventoryChanged += instanceData.OnInventoryChanged; + return instanceData; + } + + public override void OnUnassigned(GenericSkill skillSlot) + { + skillSlot.characterBody.onInventoryChanged -= ((InstanceData)skillSlot.skillInstanceData).OnInventoryChanged; + } + + public override int GetMaxStock(GenericSkill skillSlot) + { + return skillSlot.characterBody.inventory.GetItemCount(RoR2Content.Items.LunarPrimaryReplacement) * baseMaxStock; + } + + public override float GetRechargeInterval(GenericSkill skillSlot) + { + return (float)skillSlot.characterBody.inventory.GetItemCount(RoR2Content.Items.LunarPrimaryReplacement) * baseRechargeInterval; + } + + public override int GetRechargeStock(GenericSkill skillSlot) + { + return GetMaxStock(skillSlot); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/LunarSecondaryReplacementSkill.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/LunarSecondaryReplacementSkill.cs new file mode 100644 index 0000000..a432238 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/LunarSecondaryReplacementSkill.cs @@ -0,0 +1,32 @@ +namespace RoR2.Skills; + +public class LunarSecondaryReplacementSkill : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public GenericSkill skillSlot; + + public void OnInventoryChanged() + { + skillSlot.RecalculateValues(); + } + } + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + InstanceData instanceData = new InstanceData(); + instanceData.skillSlot = skillSlot; + skillSlot.characterBody.onInventoryChanged += instanceData.OnInventoryChanged; + return instanceData; + } + + public override void OnUnassigned(GenericSkill skillSlot) + { + skillSlot.characterBody.onInventoryChanged -= ((InstanceData)skillSlot.skillInstanceData).OnInventoryChanged; + } + + public override float GetRechargeInterval(GenericSkill skillSlot) + { + return (float)skillSlot.characterBody.inventory.GetItemCount(RoR2Content.Items.LunarSecondaryReplacement) * baseRechargeInterval; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/MasterSpawnSlotSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/MasterSpawnSlotSkillDef.cs new file mode 100644 index 0000000..bce243f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/MasterSpawnSlotSkillDef.cs @@ -0,0 +1,39 @@ +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/MasterSpawnSlotSkillDef")] +public class MasterSpawnSlotSkillDef : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public MasterSpawnSlotController slotController; + } + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + return new InstanceData + { + slotController = skillSlot.GetComponent() + }; + } + + private bool IsAnySlotOpen([NotNull] GenericSkill skillSlot) + { + if (skillSlot.skillInstanceData is InstanceData instanceData && (bool)instanceData.slotController) + { + return instanceData.slotController.openSlotCount > 0; + } + return false; + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (base.IsReady(skillSlot)) + { + return IsAnySlotOpen(skillSlot); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/MercDashSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/MercDashSkillDef.cs new file mode 100644 index 0000000..f60d230 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/MercDashSkillDef.cs @@ -0,0 +1,104 @@ +using EntityStates; +using EntityStates.Merc; +using HG; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/MercDashSkillDef")] +public class MercDashSkillDef : SkillDef +{ + protected class InstanceData : BaseSkillInstanceData + { + public int currentDashIndex; + + public float timeoutTimer; + + public bool waitingForHit; + + public bool hasExtraStock; + } + + public int maxDashes; + + public float timeoutDuration; + + public Sprite[] icons; + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData(); + } + + public override void OnUnassigned([NotNull] GenericSkill skillSlot) + { + base.OnUnassigned(skillSlot); + } + + public override void OnFixedUpdate([NotNull] GenericSkill skillSlot, float deltaTime) + { + base.OnFixedUpdate(skillSlot, deltaTime); + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if (instanceData.waitingForHit && skillSlot.stateMachine.state is Assaulter2 { grantAnotherDash: not false }) + { + instanceData.waitingForHit = false; + AddHit(skillSlot); + } + instanceData.timeoutTimer -= deltaTime; + if (instanceData.timeoutTimer <= 0f && instanceData.currentDashIndex != 0) + { + if (instanceData.hasExtraStock) + { + skillSlot.stock--; + instanceData.hasExtraStock = false; + } + instanceData.currentDashIndex = 0; + } + } + + protected override EntityState InstantiateNextState([NotNull] GenericSkill skillSlot) + { + EntityState entityState = base.InstantiateNextState(skillSlot); + if (entityState is PrepAssaulter2 prepAssaulter) + { + prepAssaulter.dashIndex = ((InstanceData)skillSlot.skillInstanceData).currentDashIndex; + } + return entityState; + } + + public override void OnExecute([NotNull] GenericSkill skillSlot) + { + base.OnExecute(skillSlot); + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if (!instanceData.hasExtraStock) + { + instanceData.currentDashIndex = 0; + } + instanceData.waitingForHit = true; + instanceData.hasExtraStock = false; + instanceData.timeoutTimer = timeoutDuration; + } + + protected void AddHit([NotNull] GenericSkill skillSlot) + { + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if (instanceData.currentDashIndex < maxDashes - 1) + { + instanceData.currentDashIndex++; + int stock = skillSlot.stock + 1; + skillSlot.stock = stock; + instanceData.hasExtraStock = true; + } + else + { + instanceData.currentDashIndex = 0; + } + } + + public override Sprite GetCurrentIcon([NotNull] GenericSkill skillSlot) + { + int index = ((InstanceData)skillSlot.skillInstanceData)?.currentDashIndex ?? 0; + return ArrayUtils.GetSafe(icons, index); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/PassiveItemSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/PassiveItemSkillDef.cs new file mode 100644 index 0000000..4b7cc09 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/PassiveItemSkillDef.cs @@ -0,0 +1,68 @@ +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/PassiveItem")] +public class PassiveItemSkillDef : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public bool hasItemBeenGiven; + } + + [SerializeField] + public ItemDef passiveItem; + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + InstanceData instanceData = new InstanceData + { + hasItemBeenGiven = false + }; + if (NetworkServer.active) + { + TryGiveItem(skillSlot, instanceData); + } + return instanceData; + } + + public override void OnFixedUpdate(GenericSkill skillSlot, float deltaTime) + { + if (NetworkServer.active) + { + TryGiveItem(skillSlot, (InstanceData)skillSlot.skillInstanceData); + } + } + + public override void OnUnassigned(GenericSkill skillSlot) + { + if (!NetworkServer.active) + { + return; + } + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if (instanceData.hasItemBeenGiven) + { + CharacterBody component = skillSlot.GetComponent(); + if ((bool)component && (bool)component.inventory) + { + component.inventory.RemoveItem(passiveItem); + instanceData.hasItemBeenGiven = false; + } + } + } + + private void TryGiveItem(GenericSkill skillSlot, InstanceData data) + { + if (!data.hasItemBeenGiven) + { + CharacterBody component = skillSlot.GetComponent(); + if ((bool)component && (bool)component.inventory) + { + component.inventory.GiveItem(passiveItem); + data.hasItemBeenGiven = true; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/RailgunSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/RailgunSkillDef.cs new file mode 100644 index 0000000..07c6f07 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/RailgunSkillDef.cs @@ -0,0 +1,81 @@ +using EntityStates.Railgunner.Backpack; +using EntityStates.Railgunner.Reload; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/RailgunSkillDef")] +public class RailgunSkillDef : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public EntityStateMachine backpackStateMachine; + + public EntityStateMachine reloadStateMachine; + } + + private const string backpackStateMachineName = "Backpack"; + + private const string reloadStateMachineName = "Reload"; + + [SerializeField] + public Sprite offlineIcon; + + [SerializeField] + public bool restockOnReload; + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + return new InstanceData + { + backpackStateMachine = EntityStateMachine.FindByCustomName(skillSlot.gameObject, "Backpack"), + reloadStateMachine = EntityStateMachine.FindByCustomName(skillSlot.gameObject, "Reload") + }; + } + + private bool IsBackpackOffline([NotNull] GenericSkill skillSlot) + { + if (skillSlot.skillInstanceData is InstanceData instanceData && (bool)instanceData.backpackStateMachine) + { + return instanceData.backpackStateMachine.state is Offline; + } + return false; + } + + private bool IsReloading([NotNull] GenericSkill skillSlot) + { + if (skillSlot.skillInstanceData is InstanceData instanceData && (bool)instanceData.reloadStateMachine) + { + return instanceData.reloadStateMachine.state is Reloading; + } + return false; + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (base.IsReady(skillSlot) && !IsBackpackOffline(skillSlot)) + { + return !IsReloading(skillSlot); + } + return false; + } + + public override void OnFixedUpdate([NotNull] GenericSkill skillSlot, float deltaTime) + { + base.OnFixedUpdate(skillSlot, deltaTime); + if (IsBackpackOffline(skillSlot)) + { + skillSlot.rechargeStopwatch = 0f; + } + } + + public override Sprite GetCurrentIcon([NotNull] GenericSkill skillSlot) + { + if (IsBackpackOffline(skillSlot)) + { + return offlineIcon; + } + return base.GetCurrentIcon(skillSlot); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/ReloadSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/ReloadSkillDef.cs new file mode 100644 index 0000000..b240308 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/ReloadSkillDef.cs @@ -0,0 +1,65 @@ +using EntityStates; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/ReloadSkillDef")] +public class ReloadSkillDef : SkillDef +{ + protected class InstanceData : BaseSkillInstanceData + { + public int currentStock; + + public float graceStopwatch; + } + + [Header("Reload Parameters")] + [Tooltip("The reload state to go into, when stock is less than max.")] + public SerializableEntityStateType reloadState; + + [Tooltip("The priority of this reload state.")] + public InterruptPriority reloadInterruptPriority = InterruptPriority.Skill; + + [Tooltip("The amount of time to wait between when we COULD reload, and when we actually start")] + public float graceDuration; + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData(); + } + + public override void OnUnassigned([NotNull] GenericSkill skillSlot) + { + base.OnUnassigned(skillSlot); + } + + public override void OnFixedUpdate([NotNull] GenericSkill skillSlot, float deltaTime) + { + base.OnFixedUpdate(skillSlot, deltaTime); + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + instanceData.currentStock = skillSlot.stock; + if (instanceData.currentStock >= GetMaxStock(skillSlot)) + { + return; + } + if ((bool)skillSlot.stateMachine && !skillSlot.stateMachine.HasPendingState() && skillSlot.stateMachine.CanInterruptState(reloadInterruptPriority)) + { + instanceData.graceStopwatch += deltaTime; + if (instanceData.graceStopwatch >= graceDuration || instanceData.currentStock == 0) + { + skillSlot.stateMachine.SetNextState(EntityStateCatalog.InstantiateState(ref reloadState)); + } + } + else + { + instanceData.graceStopwatch = 0f; + } + } + + public override void OnExecute([NotNull] GenericSkill skillSlot) + { + base.OnExecute(skillSlot); + ((InstanceData)skillSlot.skillInstanceData).currentStock = skillSlot.stock; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/SeekerWeaponSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/SeekerWeaponSkillDef.cs new file mode 100644 index 0000000..abd0cb3 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/SeekerWeaponSkillDef.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/SeekerWeaponSkillDef", fileName = "New SeekerSkillDef.asset")] +public class SeekerWeaponSkillDef : SteppedSkillDef +{ + public bool targetTrackingIndicator; + + public GameObject crosshairOverridePrefab; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/SkillCatalog.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/SkillCatalog.cs new file mode 100644 index 0000000..4e70906 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/SkillCatalog.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using HG; +using RoR2.ContentManagement; +using RoR2.Modding; +using UnityEngine; + +namespace RoR2.Skills; + +public static class SkillCatalog +{ + private static SkillDef[] _allSkillDefs = Array.Empty(); + + private static string[] _allSkillNames = Array.Empty(); + + private static SkillFamily[] _allSkillFamilies = Array.Empty(); + + private static string[] _allSkillFamilyNames = Array.Empty(); + + public static ResourceAvailability skillsDefined; + + public static IEnumerable allSkillDefs => _allSkillDefs; + + public static IEnumerable allSkillFamilies => _allSkillFamilies; + + [Obsolete("Use IContentPackProvider instead.")] + public static event Action> getAdditionalSkillDefs + { + add + { + LegacyModContentPackProvider.instance.HandleLegacyGetAdditionalEntries("RoR2.Skills.SkillCatalog.getAdditionalSkillDefs", value, LegacyModContentPackProvider.instance.registrationContentPack.skillDefs); + } + remove + { + } + } + + [Obsolete("Use IContentPackProvider instead.")] + public static event Action> getAdditionalSkillFamilies + { + add + { + LegacyModContentPackProvider.instance.HandleLegacyGetAdditionalEntries("RoR2.Skills.SkillCatalog.getAdditionalSkillFamilies", value, LegacyModContentPackProvider.instance.registrationContentPack.skillFamilies); + } + remove + { + } + } + + public static SkillDef GetSkillDef(int skillDefIndex) + { + return ArrayUtils.GetSafe(_allSkillDefs, skillDefIndex); + } + + public static string GetSkillName(int skillDefIndex) + { + return ArrayUtils.GetSafe(_allSkillNames, skillDefIndex); + } + + public static SkillFamily GetSkillFamily(int skillFamilyIndex) + { + return ArrayUtils.GetSafe(_allSkillFamilies, skillFamilyIndex); + } + + public static string GetSkillFamilyName(int skillFamilyIndex) + { + return ArrayUtils.GetSafe(_allSkillFamilyNames, skillFamilyIndex); + } + + public static int FindSkillIndexByName(string skillName) + { + for (int i = 0; i < _allSkillDefs.Length; i++) + { + if (_allSkillDefs[i].skillName == skillName) + { + return i; + } + } + return -1; + } + + [SystemInitializer(new Type[] { typeof(BodyCatalog) })] + private static void Init() + { + SetSkillDefs(ContentManager.skillDefs); + SetSkillFamilies(ContentManager.skillFamilies); + skillsDefined.MakeAvailable(); + } + + private static void SetSkillDefs(SkillDef[] newSkillDefs) + { + SkillDef[] array = _allSkillDefs; + for (int i = 0; i < array.Length; i++) + { + array[i].skillIndex = -1; + } + ArrayUtils.CloneTo(newSkillDefs, ref _allSkillDefs); + Array.Resize(ref _allSkillNames, _allSkillDefs.Length); + for (int j = 0; j < _allSkillDefs.Length; j++) + { + _allSkillDefs[j].skillIndex = j; + _allSkillNames[j] = ((UnityEngine.Object)_allSkillDefs[j]).name; + } + } + + private static void SetSkillFamilies(SkillFamily[] newSkillFamilies) + { + SkillFamily[] array = _allSkillFamilies; + for (int i = 0; i < array.Length; i++) + { + array[i].catalogIndex = -1; + } + ArrayUtils.CloneTo(newSkillFamilies, ref _allSkillFamilies); + Array.Resize(ref _allSkillFamilyNames, _allSkillDefs.Length); + for (int j = 0; j < _allSkillFamilies.Length; j++) + { + _allSkillFamilies[j].catalogIndex = j; + _allSkillFamilyNames[j] = ((UnityEngine.Object)_allSkillFamilies[j]).name; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/SkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/SkillDef.cs new file mode 100644 index 0000000..d17d18f --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/SkillDef.cs @@ -0,0 +1,228 @@ +using System; +using EntityStates; +using JetBrains.Annotations; +using UnityEngine; +using UnityEngine.Serialization; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/Generic")] +public class SkillDef : ScriptableObject +{ + public class BaseSkillInstanceData + { + } + + [Tooltip("The name of the skill. This is mainly for purposes of identification in the inspector and currently has no direct effect.")] + [Header("Skill Identifier")] + public string skillName = ""; + + [Tooltip("The language token with the name of this skill.")] + [Header("User-Facing Info")] + public string skillNameToken = ""; + + [Tooltip("The language token with the description of this skill.")] + public string skillDescriptionToken = ""; + + [Tooltip("Extra tooltips when hovered over in character select. Currently only used in that area!")] + public string[] keywordTokens; + + [Tooltip("The icon to display for this skill.")] + [ShowThumbnail] + public Sprite icon; + + [Header("State Machine Parameters")] + [Tooltip("The state machine this skill operates upon.")] + public string activationStateMachineName; + + [Tooltip("The state to enter when this skill is activated.")] + public SerializableEntityStateType activationState; + + [Tooltip("The priority of this skill.")] + public InterruptPriority interruptPriority = InterruptPriority.Skill; + + [Tooltip("How long it takes for this skill to recharge after being used.")] + [Header("Stock and Cooldown")] + public float baseRechargeInterval = 1f; + + [Tooltip("Maximum number of charges this skill can carry.")] + public int baseMaxStock = 1; + + [Tooltip("How much stock to restore on a recharge.")] + public int rechargeStock = 1; + + [Tooltip("How much stock is required to activate this skill.")] + public int requiredStock = 1; + + [Tooltip("How much stock to deduct when the skill is activated.")] + public int stockToConsume = 1; + + [Tooltip("Makes the skill restock interval divided by attack speed if checked.")] + public bool attackSpeedBuffsRestockSpeed; + + [Tooltip("Increases the efficacy of attack speed on restock time.")] + [Range(1f, 10f)] + public float attackSpeedBuffsRestockSpeed_Multiplier = 1f; + + [Tooltip("Whether or not it resets any progress on cooldowns.")] + [Header("Optional Parameters, Stock")] + [FormerlySerializedAs("isBullets")] + public bool resetCooldownTimerOnUse; + + [Tooltip("Whether or not to fully restock this skill when it's assigned.")] + public bool fullRestockOnAssign = true; + + [Tooltip("Whether or not this skill can hold past it's maximum stock.")] + public bool dontAllowPastMaxStocks; + + [Tooltip("Whether or not the cooldown waits until it leaves the set state")] + public bool beginSkillCooldownOnSkillEnd; + + [Tooltip("Whether or not activating the skill forces off sprinting.")] + [FormerlySerializedAs("noSprint")] + [Header("Optional Parameters, Sprinting")] + public bool cancelSprintingOnActivation = true; + + [FormerlySerializedAs("mobilitySkill")] + [Tooltip("Whether or not this skill is considered 'mobility'. Currently just forces sprint.")] + public bool forceSprintDuringState; + + [Tooltip("Whether or not sprinting sets the skill's state to be reset.")] + public bool canceledFromSprinting; + + [Header("Optional Parameters, Misc")] + [Tooltip("Whether or not this is considered a combat skill.")] + public bool isCombatSkill = true; + + [Tooltip("The skill can't be activated if the key is held.")] + public bool mustKeyPress; + + [Tooltip("If true, CharacterBody handles LuminiousShot buffs. If false, the skill must handle it.")] + public bool autoHandleLuminousShot = true; + + [Tooltip("If true, the SkillIcon will not show this skill's stock count.")] + public bool hideStockCount; + + [Obsolete("Accessing UnityEngine.Object.Name causes allocations on read. Look up the name from the catalog instead. If absolutely necessary to perform direct access, cast to ScriptableObject first.")] + public new string name => null; + + public int skillIndex { get; set; } + + public virtual BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return null; + } + + public virtual void OnUnassigned([NotNull] GenericSkill skillSlot) + { + } + + public virtual Sprite GetCurrentIcon([NotNull] GenericSkill skillSlot) + { + return icon; + } + + public virtual string GetCurrentNameToken([NotNull] GenericSkill skillSlot) + { + return skillNameToken; + } + + public virtual string GetCurrentDescriptionToken([NotNull] GenericSkill skillSlot) + { + return skillDescriptionToken; + } + + protected bool HasRequiredStockAndDelay([NotNull] GenericSkill skillSlot) + { + return skillSlot.stock >= requiredStock; + } + + public virtual bool CanExecute([NotNull] GenericSkill skillSlot) + { + if (HasRequiredStockAndDelay(skillSlot) && IsReady(skillSlot) && (bool)skillSlot.stateMachine && !skillSlot.stateMachine.HasPendingState()) + { + return skillSlot.stateMachine.CanInterruptState(interruptPriority); + } + return false; + } + + public virtual bool IsReady([NotNull] GenericSkill skillSlot) + { + return HasRequiredStockAndDelay(skillSlot); + } + + protected virtual EntityState InstantiateNextState([NotNull] GenericSkill skillSlot) + { + EntityState entityState = EntityStateCatalog.InstantiateState(ref activationState); + if (entityState is ISkillState skillState) + { + skillState.activatorSkillSlot = skillSlot; + } + return entityState; + } + + public virtual void OnExecute([NotNull] GenericSkill skillSlot) + { + skillSlot.stateMachine.SetInterruptState(InstantiateNextState(skillSlot), interruptPriority); + if (cancelSprintingOnActivation) + { + skillSlot.characterBody.isSprinting = false; + } + skillSlot.stock -= stockToConsume; + if (resetCooldownTimerOnUse) + { + skillSlot.rechargeStopwatch = 0f; + } + if ((bool)skillSlot.characterBody) + { + skillSlot.characterBody.OnSkillActivated(skillSlot); + } + } + + public virtual void OnFixedUpdate([NotNull] GenericSkill skillSlot, float deltaTime) + { + skillSlot.RunRecharge(deltaTime); + if (((canceledFromSprinting && skillSlot.characterBody.isSprinting) || forceSprintDuringState) && skillSlot.stateMachine.state.GetType() == activationState.stateType) + { + if (canceledFromSprinting && skillSlot.characterBody.isSprinting) + { + skillSlot.stateMachine.SetNextStateToMain(); + } + if (forceSprintDuringState) + { + skillSlot.characterBody.isSprinting = true; + } + } + } + + public bool IsAlreadyInState([NotNull] GenericSkill skillSlot) + { + return skillSlot?.stateMachine.state.GetType() == activationState.stateType; + } + + public virtual int GetMaxStock([NotNull] GenericSkill skillSlot) + { + return baseMaxStock; + } + + public virtual int GetRechargeStock([NotNull] GenericSkill skillSlot) + { + return rechargeStock; + } + + public virtual float GetRechargeInterval([NotNull] GenericSkill skillSlot) + { + if (attackSpeedBuffsRestockSpeed) + { + float num = skillSlot.characterBody.attackSpeed - skillSlot.characterBody.baseAttackSpeed; + num *= attackSpeedBuffsRestockSpeed_Multiplier; + num += 1f; + if (num < 0.5f) + { + num = 0.5f; + } + return baseRechargeInterval / num; + } + return baseRechargeInterval; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/SkillFamily.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/SkillFamily.cs new file mode 100644 index 0000000..030f6a6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/SkillFamily.cs @@ -0,0 +1,84 @@ +using System; +using UnityEngine; +using UnityEngine.Serialization; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillFamily")] +public class SkillFamily : ScriptableObject +{ + [Serializable] + public struct Variant + { + public SkillDef skillDef; + + [Obsolete("Use 'unlockableDef' instead.")] + public string unlockableName; + + public UnlockableDef unlockableDef; + + public ViewablesCatalog.Node viewableNode { get; set; } + } + + [FormerlySerializedAs("Entries")] + public Variant[] variants = Array.Empty(); + + [FormerlySerializedAs("defaultEntryIndex")] + public uint defaultVariantIndex; + + [Obsolete("Accessing UnityEngine.Object.Name causes allocations on read. Look up the name from the catalog instead. If absolutely necessary to perform direct access, cast to ScriptableObject first.")] + public new string name => null; + + public int catalogIndex { get; set; } + + public SkillDef defaultSkillDef => variants[defaultVariantIndex].skillDef; + + public void OnValidate() + { + string text = base.name; + if (variants == null) + { + Debug.LogError("Skill Family \"" + text + "\" Has no Variants"); + } + else if (defaultVariantIndex >= variants.Length) + { + Debug.LogError($"Skill Family \"{text}\" defaultVariantIndex ({defaultVariantIndex}) is outside the bounds of the variants array ({variants.Length})."); + } + } + + public string GetVariantName(int variantIndex) + { + return SkillCatalog.GetSkillName(variants[variantIndex].skillDef.skillIndex); + } + + public int GetVariantIndex(string variantName) + { + for (int i = 0; i < variants.Length; i++) + { + if (GetVariantName(i).Equals(variantName, StringComparison.Ordinal)) + { + return i; + } + } + return -1; + } + + [ContextMenu("Upgrade unlockableName to unlockableDef")] + public void UpgradeUnlockableNameToUnlockableDef() + { + for (int i = 0; i < variants.Length; i++) + { + ref Variant reference = ref variants[i]; + if (!string.IsNullOrEmpty(reference.unlockableName) && !reference.unlockableDef) + { + UnlockableDef unlockableDef = LegacyResourcesAPI.Load("UnlockableDefs/" + reference.unlockableName); + if ((bool)unlockableDef) + { + reference.unlockableDef = unlockableDef; + reference.unlockableName = null; + } + } + } + EditorUtil.SetDirty(this); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/SteppedSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/SteppedSkillDef.cs new file mode 100644 index 0000000..8a58d93 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/SteppedSkillDef.cs @@ -0,0 +1,69 @@ +using EntityStates; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +public class SteppedSkillDef : SkillDef +{ + public class InstanceData : BaseSkillInstanceData + { + public int step; + } + + public interface IStepSetter + { + void SetStep(int i); + } + + public int stepCount = 2; + + [Tooltip("The amount of time a step is 'held' before it resets. Only begins to count down when available to execute.")] + public float stepGraceDuration = 0.1f; + + private float stepResetTimer; + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData(); + } + + protected override EntityState InstantiateNextState([NotNull] GenericSkill skillSlot) + { + EntityState entityState = base.InstantiateNextState(skillSlot); + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if (entityState is IStepSetter stepSetter) + { + stepSetter.SetStep(instanceData.step); + } + return entityState; + } + + public override void OnExecute([NotNull] GenericSkill skillSlot) + { + base.OnExecute(skillSlot); + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + instanceData.step++; + if (instanceData.step >= stepCount) + { + instanceData.step = 0; + } + } + + public override void OnFixedUpdate([NotNull] GenericSkill skillSlot, float deltaTime) + { + base.OnFixedUpdate(skillSlot, deltaTime); + if (skillSlot.CanExecute()) + { + stepResetTimer += deltaTime; + } + else + { + stepResetTimer = 0f; + } + if (stepResetTimer > stepGraceDuration) + { + ((InstanceData)skillSlot.skillInstanceData).step = 0; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/ToolbotWeaponSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/ToolbotWeaponSkillDef.cs new file mode 100644 index 0000000..62275fe --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/ToolbotWeaponSkillDef.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +namespace RoR2.Skills; + +public class ToolbotWeaponSkillDef : SkillDef +{ + public string stanceName; + + public string entrySound; + + public string entryAnimState; + + public string enterGestureAnimState; + + public string exitAnimState; + + public string exitGestureAnimState; + + public int animatorWeaponIndex; + + public GameObject crosshairPrefab; + + public AnimationCurve crosshairSpreadCurve; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/VoidRaidCrabBodySkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidRaidCrabBodySkillDef.cs new file mode 100644 index 0000000..b9f3444 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidRaidCrabBodySkillDef.cs @@ -0,0 +1,41 @@ +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/VoidRaidCrabBodySkillDef")] +public class VoidRaidCrabBodySkillDef : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public EntityStateMachine weaponStateMachine; + } + + private const string weaponStateMachineName = "Weapon"; + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + return new InstanceData + { + weaponStateMachine = EntityStateMachine.FindByCustomName(skillSlot.gameObject, "Weapon") + }; + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (base.IsReady(skillSlot)) + { + return !IsWeaponBusy(skillSlot); + } + return false; + } + + private bool IsWeaponBusy([NotNull] GenericSkill skillSlot) + { + if (skillSlot.skillInstanceData is InstanceData instanceData && (bool)instanceData.weaponStateMachine) + { + return !instanceData.weaponStateMachine.IsInMainState(); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/VoidRaidCrabWeaponSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidRaidCrabWeaponSkillDef.cs new file mode 100644 index 0000000..885be8d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidRaidCrabWeaponSkillDef.cs @@ -0,0 +1,56 @@ +using EntityStates; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +[CreateAssetMenu(menuName = "RoR2/SkillDef/VoidRaidCrabWeaponSkillDef")] +public class VoidRaidCrabWeaponSkillDef : SkillDef +{ + private class InstanceData : BaseSkillInstanceData + { + public EntityStateMachine bodyStateMachine; + + public EntityStateMachine weaponStateMachine; + } + + private const string bodyStateMachineName = "Body"; + + private const string weaponStateMachineName = "Weapon"; + + public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot) + { + return new InstanceData + { + bodyStateMachine = EntityStateMachine.FindByCustomName(skillSlot.gameObject, "Body"), + weaponStateMachine = EntityStateMachine.FindByCustomName(skillSlot.gameObject, "Weapon") + }; + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (base.IsReady(skillSlot) && CanReceiveInput(skillSlot)) + { + return !IsWeaponBusy(skillSlot); + } + return false; + } + + private bool CanReceiveInput([NotNull] GenericSkill skillSlot) + { + if (skillSlot.skillInstanceData is InstanceData instanceData && (bool)instanceData.bodyStateMachine) + { + return instanceData.bodyStateMachine.state is GenericCharacterMain; + } + return false; + } + + private bool IsWeaponBusy([NotNull] GenericSkill skillSlot) + { + if (skillSlot.skillInstanceData is InstanceData instanceData && (bool)instanceData.weaponStateMachine) + { + return !instanceData.weaponStateMachine.IsInMainState(); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/VoidSurvivorBlasterSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidSurvivorBlasterSkillDef.cs new file mode 100644 index 0000000..fdc145a --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidSurvivorBlasterSkillDef.cs @@ -0,0 +1,28 @@ +using EntityStates; +using EntityStates.VoidSurvivor.Weapon; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Skills; + +public class VoidSurvivorBlasterSkillDef : SteppedSkillDef +{ + public Sprite[] icons; + + protected override EntityState InstantiateNextState([NotNull] GenericSkill skillSlot) + { + EntityState entityState = base.InstantiateNextState(skillSlot); + VoidSurvivorController component = skillSlot.GetComponent(); + if ((bool)component) + { + float corruptionPercentage = component.corruptionPercentage; + entityState = ((corruptionPercentage >= 75f) ? new FireBlaster4() : ((corruptionPercentage >= 50f) ? new FireBlaster3() : ((!(corruptionPercentage >= 25f)) ? ((FireBlasterBase)new FireBlaster1()) : ((FireBlasterBase)new FireBlaster2())))); + } + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if (entityState is IStepSetter stepSetter) + { + stepSetter.SetStep(instanceData.step); + } + return entityState; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Skills/VoidSurvivorSkillDef.cs b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidSurvivorSkillDef.cs new file mode 100644 index 0000000..e954a68 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Skills/VoidSurvivorSkillDef.cs @@ -0,0 +1,42 @@ +using JetBrains.Annotations; + +namespace RoR2.Skills; + +public class VoidSurvivorSkillDef : SkillDef +{ + protected class InstanceData : BaseSkillInstanceData + { + public VoidSurvivorController voidSurvivorController; + } + + public float minimumCorruption; + + public float maximumCorruption; + + public override BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot) + { + return new InstanceData + { + voidSurvivorController = skillSlot.GetComponent() + }; + } + + public override bool IsReady([NotNull] GenericSkill skillSlot) + { + if (base.IsReady(skillSlot)) + { + return HasRequiredCorruption(skillSlot); + } + return false; + } + + public bool HasRequiredCorruption([NotNull] GenericSkill skillSlot) + { + InstanceData instanceData = (InstanceData)skillSlot.skillInstanceData; + if ((bool)instanceData.voidSurvivorController && instanceData.voidSurvivorController.corruption >= minimumCorruption && instanceData.voidSurvivorController.corruption < maximumCorruption) + { + return true; + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Social/SocialUserId.cs b/ilspy_dump/ror2_csproj/RoR2.Social/SocialUserId.cs new file mode 100644 index 0000000..32ceb5b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Social/SocialUserId.cs @@ -0,0 +1,11 @@ +namespace RoR2.Social; + +public struct SocialUserId +{ + public readonly PlatformID steamId; + + public SocialUserId(PlatformID steamId) + { + this.steamId = steamId; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/PerBodyStatDef.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/PerBodyStatDef.cs new file mode 100644 index 0000000..242101e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/PerBodyStatDef.cs @@ -0,0 +1,126 @@ +using System.Collections.Generic; +using System.Globalization; +using HG; + +namespace RoR2.Stats; + +public class PerBodyStatDef +{ + private readonly string prefix; + + private readonly StatRecordType recordType; + + private readonly StatDataType dataType; + + private readonly StatDef.DisplayValueFormatterDelegate displayValueFormatter; + + private readonly Dictionary bodyNameToStatDefDictionary = new Dictionary(); + + public readonly string nameToken; + + private StatDef[] bodyIndexToStatDef; + + private static readonly List instancesList; + + public static readonly PerBodyStatDef totalTimeAlive; + + public static readonly PerBodyStatDef totalWins; + + public static readonly PerBodyStatDef longestRun; + + public static readonly PerBodyStatDef damageDealtTo; + + public static readonly PerBodyStatDef damageDealtAs; + + public static readonly PerBodyStatDef minionDamageDealtAs; + + public static readonly PerBodyStatDef damageTakenFrom; + + public static readonly PerBodyStatDef damageTakenAs; + + public static readonly PerBodyStatDef killsAgainst; + + public static readonly PerBodyStatDef killsAgainstElite; + + public static readonly PerBodyStatDef deathsFrom; + + public static readonly PerBodyStatDef killsAs; + + public static readonly PerBodyStatDef minionKillsAs; + + public static readonly PerBodyStatDef deathsAs; + + public static readonly PerBodyStatDef timesPicked; + + public static readonly PerBodyStatDef highestInfiniteTowerWaveReachedEasy; + + public static readonly PerBodyStatDef highestInfiniteTowerWaveReachedNormal; + + public static readonly PerBodyStatDef highestInfiniteTowerWaveReachedHard; + + static PerBodyStatDef() + { + instancesList = new List(); + totalTimeAlive = Register("totalTimeAlive", StatRecordType.Sum, StatDataType.Double); + totalWins = Register("totalWins", StatRecordType.Sum, StatDataType.ULong); + longestRun = Register("longestRun", StatRecordType.Max, StatDataType.Double, StatDef.TimeMMSSDisplayValueFormatter); + damageDealtTo = Register("damageDealtTo", StatRecordType.Sum, StatDataType.ULong); + damageDealtAs = Register("damageDealtAs", StatRecordType.Sum, StatDataType.ULong); + minionDamageDealtAs = Register("minionDamageDealtAs", StatRecordType.Sum, StatDataType.ULong); + damageTakenFrom = Register("damageTakenFrom", StatRecordType.Sum, StatDataType.ULong); + damageTakenAs = Register("damageTakenAs", StatRecordType.Sum, StatDataType.ULong); + killsAgainst = Register("killsAgainst", StatRecordType.Sum, StatDataType.ULong); + killsAgainstElite = Register("killsAgainstElite", StatRecordType.Sum, StatDataType.ULong); + deathsFrom = Register("deathsFrom", StatRecordType.Sum, StatDataType.ULong); + killsAs = Register("killsAs", StatRecordType.Sum, StatDataType.ULong); + minionKillsAs = Register("minionKillsAs", StatRecordType.Sum, StatDataType.ULong); + deathsAs = Register("deathsAs", StatRecordType.Sum, StatDataType.ULong); + timesPicked = Register("timesPicked", StatRecordType.Sum, StatDataType.ULong); + highestInfiniteTowerWaveReachedEasy = Register("highestInfiniteTowerWaveReachedEasy", StatRecordType.Max, StatDataType.ULong); + highestInfiniteTowerWaveReachedNormal = Register("highestInfiniteTowerWaveReachedNormal", StatRecordType.Max, StatDataType.ULong); + highestInfiniteTowerWaveReachedHard = Register("highestInfiniteTowerWaveReachedHard", StatRecordType.Max, StatDataType.ULong); + } + + public static void RegisterStatDefs() + { + foreach (PerBodyStatDef instances in instancesList) + { + instances.bodyIndexToStatDef = new StatDef[BodyCatalog.bodyCount]; + for (BodyIndex bodyIndex = (BodyIndex)0; (int)bodyIndex < BodyCatalog.bodyCount; bodyIndex++) + { + string bodyName = BodyCatalog.GetBodyName(bodyIndex); + StatDef statDef = StatDef.Register(instances.prefix + "." + bodyName, instances.recordType, instances.dataType, 0.0, instances.displayValueFormatter); + instances.bodyNameToStatDefDictionary.Add(bodyName, statDef); + instances.bodyNameToStatDefDictionary.Add(bodyName + "(Clone)", statDef); + instances.bodyIndexToStatDef[(int)bodyIndex] = statDef; + } + } + } + + private PerBodyStatDef(string prefix, StatRecordType recordType, StatDataType dataType, StatDef.DisplayValueFormatterDelegate displayValueFormatter = null) + { + this.prefix = prefix; + this.recordType = recordType; + this.dataType = dataType; + this.displayValueFormatter = displayValueFormatter; + nameToken = "PERBODYSTATNAME_" + prefix.ToUpper(CultureInfo.InvariantCulture); + } + + private static PerBodyStatDef Register(string prefix, StatRecordType recordType, StatDataType dataType, StatDef.DisplayValueFormatterDelegate displayValueFormatter = null) + { + PerBodyStatDef perBodyStatDef = new PerBodyStatDef(prefix, recordType, dataType, displayValueFormatter); + instancesList.Add(perBodyStatDef); + return perBodyStatDef; + } + + public StatDef FindStatDef(string bodyName) + { + bodyNameToStatDefDictionary.TryGetValue(bodyName, out var value); + return value; + } + + public StatDef FindStatDef(BodyIndex bodyIndex) + { + return ArrayUtils.GetSafe(bodyIndexToStatDef, (int)bodyIndex); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/PerEquipmentStatDef.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/PerEquipmentStatDef.cs new file mode 100644 index 0000000..c1d1eb0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/PerEquipmentStatDef.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; + +namespace RoR2.Stats; + +public class PerEquipmentStatDef +{ + private readonly string prefix; + + private readonly StatRecordType recordType; + + private readonly StatDataType dataType; + + private readonly StatDef[] keyToStatDef = EquipmentCatalog.GetPerEquipmentBuffer(); + + private StatDef.DisplayValueFormatterDelegate displayValueFormatter; + + private static readonly List instancesList; + + public static readonly PerEquipmentStatDef totalTimeHeld; + + public static readonly PerEquipmentStatDef totalTimesFired; + + static PerEquipmentStatDef() + { + instancesList = new List(); + totalTimeHeld = Register("totalTimeHeld", StatRecordType.Sum, StatDataType.Double, StatDef.TimeMMSSDisplayValueFormatter); + totalTimesFired = Register("totalTimesFired", StatRecordType.Sum, StatDataType.ULong); + } + + public static void RegisterStatDefs() + { + foreach (PerEquipmentStatDef instances in instancesList) + { + foreach (EquipmentIndex item in EquipmentCatalog.allEquipment) + { + EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(item); + StatDef statDef = StatDef.Register(instances.prefix + "." + equipmentDef.name, instances.recordType, instances.dataType, 0.0, instances.displayValueFormatter); + instances.keyToStatDef[(int)item] = statDef; + } + } + } + + private PerEquipmentStatDef(string prefix, StatRecordType recordType, StatDataType dataType, StatDef.DisplayValueFormatterDelegate displayValueFormatter) + { + this.prefix = prefix; + this.recordType = recordType; + this.dataType = dataType; + this.displayValueFormatter = displayValueFormatter ?? new StatDef.DisplayValueFormatterDelegate(StatDef.DefaultDisplayValueFormatter); + } + + private static PerEquipmentStatDef Register(string prefix, StatRecordType recordType, StatDataType dataType, StatDef.DisplayValueFormatterDelegate displayValueFormatter = null) + { + PerEquipmentStatDef perEquipmentStatDef = new PerEquipmentStatDef(prefix, recordType, dataType, displayValueFormatter); + instancesList.Add(perEquipmentStatDef); + return perEquipmentStatDef; + } + + public StatDef FindStatDef(EquipmentIndex key) + { + return keyToStatDef[(int)key]; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/PerItemStatDef.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/PerItemStatDef.cs new file mode 100644 index 0000000..9fabb2d --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/PerItemStatDef.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; + +namespace RoR2.Stats; + +public class PerItemStatDef +{ + private readonly string prefix; + + private readonly StatRecordType recordType; + + private readonly StatDataType dataType; + + private readonly StatDef[] keyToStatDef = ItemCatalog.GetPerItemBuffer(); + + private static readonly List instancesList; + + public static readonly PerItemStatDef totalCollected; + + public static readonly PerItemStatDef highestCollected; + + static PerItemStatDef() + { + instancesList = new List(); + totalCollected = Register("totalCollected", StatRecordType.Sum, StatDataType.ULong); + highestCollected = Register("highestCollected", StatRecordType.Max, StatDataType.ULong); + } + + public static void RegisterStatDefs() + { + foreach (PerItemStatDef instances in instancesList) + { + foreach (ItemIndex allItem in ItemCatalog.allItems) + { + ItemDef itemDef = ItemCatalog.GetItemDef(allItem); + StatDef statDef = StatDef.Register(instances.prefix + "." + itemDef.name, instances.recordType, instances.dataType, 0.0); + instances.keyToStatDef[(int)allItem] = statDef; + } + } + } + + private PerItemStatDef(string prefix, StatRecordType recordType, StatDataType dataType) + { + this.prefix = prefix; + this.recordType = recordType; + this.dataType = dataType; + } + + private static PerItemStatDef Register(string prefix, StatRecordType recordType, StatDataType dataType) + { + PerItemStatDef perItemStatDef = new PerItemStatDef(prefix, recordType, dataType); + instancesList.Add(perItemStatDef); + return perItemStatDef; + } + + public StatDef FindStatDef(ItemIndex key) + { + return keyToStatDef[(int)key]; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/PerStageStatDef.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/PerStageStatDef.cs new file mode 100644 index 0000000..f0a5c16 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/PerStageStatDef.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace RoR2.Stats; + +public class PerStageStatDef +{ + private readonly string prefix; + + private readonly StatRecordType recordType; + + private readonly StatDataType dataType; + + private readonly Dictionary keyToStatDef = new Dictionary(); + + private StatDef.DisplayValueFormatterDelegate displayValueFormatter; + + private static readonly List instancesList; + + public static readonly PerStageStatDef totalTimesVisited; + + public static readonly PerStageStatDef totalTimesCleared; + + static PerStageStatDef() + { + instancesList = new List(); + totalTimesVisited = Register("totalTimesVisited", StatRecordType.Sum, StatDataType.ULong); + totalTimesCleared = Register("totalTimesCleared", StatRecordType.Sum, StatDataType.ULong); + } + + public static void RegisterStatDefs() + { + foreach (PerStageStatDef instances in instancesList) + { + foreach (string allBaseSceneName in SceneCatalog.allBaseSceneNames) + { + StatDef value = StatDef.Register(instances.prefix + "." + allBaseSceneName, instances.recordType, instances.dataType, 0.0, instances.displayValueFormatter); + instances.keyToStatDef[allBaseSceneName] = value; + } + } + } + + private PerStageStatDef(string prefix, StatRecordType recordType, StatDataType dataType, StatDef.DisplayValueFormatterDelegate displayValueFormatter) + { + this.prefix = prefix; + this.recordType = recordType; + this.dataType = dataType; + this.displayValueFormatter = displayValueFormatter ?? new StatDef.DisplayValueFormatterDelegate(StatDef.DefaultDisplayValueFormatter); + } + + [NotNull] + private static PerStageStatDef Register(string prefix, StatRecordType recordType, StatDataType dataType, StatDef.DisplayValueFormatterDelegate displayValueFormatter = null) + { + PerStageStatDef perStageStatDef = new PerStageStatDef(prefix, recordType, dataType, displayValueFormatter); + instancesList.Add(perStageStatDef); + return perStageStatDef; + } + + [CanBeNull] + public StatDef FindStatDef(string key) + { + if (keyToStatDef.TryGetValue(key, out var value)) + { + return value; + } + return null; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/PlayerStatsComponent.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/PlayerStatsComponent.cs new file mode 100644 index 0000000..edcc0fb --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/PlayerStatsComponent.cs @@ -0,0 +1,283 @@ +using System.Collections.Generic; +using RoR2.Networking; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.Stats; + +[RequireComponent(typeof(PlayerCharacterMasterController))] +[RequireComponent(typeof(CharacterMaster))] +public class PlayerStatsComponent : NetworkBehaviour +{ + public static readonly List instancesList = new List(); + + private float serverTransmitTimer; + + private float serverTransmitInterval = 10f; + + private Vector3 previousBodyPosition; + + private GameObject cachedBodyObject; + + private CharacterBody cachedCharacterBody; + + private CharacterMotor cachedBodyCharacterMotor; + + private Transform cachedBodyTransform; + + public StatSheet currentStats; + + private StatSheet clientDeltaStatsBuffer; + + private StatSheet recordedStats; + + public CharacterMaster characterMaster { get; private set; } + + public PlayerCharacterMasterController playerCharacterMasterController { get; private set; } + + private void Awake() + { + playerCharacterMasterController = GetComponent(); + characterMaster = GetComponent(); + instancesList.Add(this); + currentStats = StatSheet.New(); + if (NetworkClient.active) + { + recordedStats = StatSheet.New(); + clientDeltaStatsBuffer = StatSheet.New(); + } + } + + private void OnDestroy() + { + if (NetworkServer.active) + { + SendUpdateToClient(); + } + instancesList.Remove(this); + } + + public static StatSheet FindBodyStatSheet(GameObject bodyObject) + { + if (!bodyObject) + { + return null; + } + return FindBodyStatSheet(bodyObject.GetComponent()); + } + + public static StatSheet FindBodyStatSheet(CharacterBody characterBody) + { + return characterBody?.master?.GetComponent()?.currentStats; + } + + public static StatSheet FindMasterStatSheet(CharacterMaster master) + { + return FindMasterStatsComponent(master)?.currentStats; + } + + public static PlayerStatsComponent FindBodyStatsComponent(GameObject bodyObject) + { + if (!bodyObject) + { + return null; + } + return FindBodyStatsComponent(bodyObject.GetComponent()); + } + + public static PlayerStatsComponent FindBodyStatsComponent(CharacterBody characterBody) + { + return characterBody?.master?.GetComponent(); + } + + public static PlayerStatsComponent FindMasterStatsComponent(CharacterMaster master) + { + return master?.playerStatsComponent; + } + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void Init() + { + GlobalEventManager.onCharacterDeathGlobal += delegate(DamageReport damageReport) + { + if (NetworkServer.active) + { + PlayerStatsComponent playerStatsComponent = FindBodyStatsComponent(damageReport.victim.gameObject); + if ((bool)playerStatsComponent) + { + playerStatsComponent.serverTransmitTimer = 0f; + } + } + }; + } + + private void FixedUpdate() + { + if (NetworkServer.active) + { + ServerFixedUpdate(); + } + } + + [Server] + public void ForceNextTransmit() + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.Stats.PlayerStatsComponent::ForceNextTransmit()' called on client"); + } + else + { + serverTransmitTimer = 0f; + } + } + + [Server] + private void ServerFixedUpdate() + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.Stats.PlayerStatsComponent::ServerFixedUpdate()' called on client"); + return; + } + float num = 0f; + float runTime = 0f; + if ((bool)Run.instance && !Run.instance.isRunStopwatchPaused) + { + num = Time.fixedDeltaTime; + runTime = Run.instance.GetRunStopwatch(); + } + StatManager.CharacterUpdateEvent e = default(StatManager.CharacterUpdateEvent); + e.statsComponent = this; + e.runTime = runTime; + GameObject bodyObject = characterMaster.GetBodyObject(); + if (bodyObject != cachedBodyObject) + { + cachedBodyObject = bodyObject; + cachedBodyObject = bodyObject; + cachedBodyTransform = bodyObject?.transform; + if ((bool)cachedBodyTransform) + { + previousBodyPosition = cachedBodyTransform.position; + } + cachedCharacterBody = bodyObject?.GetComponent(); + cachedBodyCharacterMotor = bodyObject?.GetComponent(); + } + if ((bool)cachedBodyTransform) + { + Vector3 position = cachedBodyTransform.position; + e.additionalDistanceTraveled = Vector3.Distance(position, previousBodyPosition); + previousBodyPosition = position; + } + if (characterMaster.hasBody) + { + e.additionalTimeAlive += num; + } + if ((bool)cachedCharacterBody) + { + e.level = (int)cachedCharacterBody.level; + } + StatManager.PushCharacterUpdateEvent(e); + serverTransmitTimer -= Time.fixedDeltaTime; + if (serverTransmitTimer <= 0f) + { + serverTransmitTimer = serverTransmitInterval; + SendUpdateToClient(); + } + } + + [Server] + private void SendUpdateToClient() + { + if (!NetworkServer.active) + { + Debug.LogWarning("[Server] function 'System.Void RoR2.Stats.PlayerStatsComponent::SendUpdateToClient()' called on client"); + return; + } + NetworkUser networkUser = playerCharacterMasterController.networkUser; + if ((bool)networkUser) + { + NetworkWriter networkWriter = new NetworkWriter(); + networkWriter.StartMessage(58); + networkWriter.Write(base.gameObject); + currentStats.WriteChanges(networkWriter); + networkWriter.FinishMessage(); + networkUser.connectionToClient.SendWriter(networkWriter, GetNetworkChannel()); + } + } + + [NetworkMessageHandler(client = true, msgType = 58)] + private static void HandleStatsUpdate(NetworkMessage netMsg) + { + GameObject gameObject = netMsg.reader.ReadGameObject(); + if ((bool)gameObject) + { + PlayerStatsComponent component = gameObject.GetComponent(); + if ((bool)component) + { + component.InstanceHandleStatsUpdate(netMsg.reader); + } + } + } + + [Client] + private void InstanceHandleStatsUpdate(NetworkReader reader) + { + if (!NetworkClient.active) + { + Debug.LogWarning("[Client] function 'System.Void RoR2.Stats.PlayerStatsComponent::InstanceHandleStatsUpdate(UnityEngine.Networking.NetworkReader)' called on server"); + return; + } + if (!NetworkServer.active) + { + currentStats.Read(reader); + } + FlushStatsToUserProfile(); + } + + [Client] + private void FlushStatsToUserProfile() + { + if (!NetworkClient.active) + { + Debug.LogWarning("[Client] function 'System.Void RoR2.Stats.PlayerStatsComponent::FlushStatsToUserProfile()' called on server"); + return; + } + StatSheet.GetDelta(clientDeltaStatsBuffer, currentStats, recordedStats); + currentStats.ClearHasChangedFlags(); + StatSheet.Copy(currentStats, recordedStats); + (playerCharacterMasterController.networkUser?.localUser)?.userProfile?.ApplyDeltaStatSheet(clientDeltaStatsBuffer); + } + + [ConCommand(commandName = "print_stats", flags = ConVarFlags.None, helpText = "Prints all current stats of the sender.")] + private static void CCPrintStats(ConCommandArgs args) + { + StatSheet statSheet = args.senderMasterObject?.GetComponent()?.currentStats; + if (statSheet != null) + { + string[] array = new string[statSheet.fields.Length]; + for (int i = 0; i < array.Length; i++) + { + array[i] = $"[\"{statSheet.fields[i].name}\"]={statSheet.fields[i].ToString()}"; + } + } + } + + private void UNetVersion() + { + } + + public override bool OnSerialize(NetworkWriter writer, bool forceAll) + { + bool result = default(bool); + return result; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + } + + public override void PreStartClient() + { + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatDataType.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatDataType.cs new file mode 100644 index 0000000..3aba002 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatDataType.cs @@ -0,0 +1,7 @@ +namespace RoR2.Stats; + +public enum StatDataType +{ + ULong, + Double +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatDef.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatDef.cs new file mode 100644 index 0000000..48022fc --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatDef.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using JetBrains.Annotations; + +namespace RoR2.Stats; + +public class StatDef +{ + public delegate string DisplayValueFormatterDelegate(ref StatField statField); + + public static readonly List allStatDefs; + + private static readonly Dictionary nameToStatDef; + + public int index; + + public readonly string name; + + public readonly string displayToken; + + public readonly StatRecordType recordType; + + public readonly StatDataType dataType; + + public double pointValue; + + public readonly DisplayValueFormatterDelegate displayValueFormatter; + + public Action onChangeCallback; + + public static readonly StatDef totalGamesPlayed; + + public static readonly StatDef totalTimeAlive; + + public static readonly StatDef totalKills; + + public static readonly StatDef totalMinionKills; + + public static readonly StatDef totalDeaths; + + public static readonly StatDef totalDamageDealt; + + public static readonly StatDef totalMinionDamageDealt; + + public static readonly StatDef totalDamageTaken; + + public static readonly StatDef totalHealthHealed; + + public static readonly StatDef highestDamageDealt; + + public static readonly StatDef highestLevel; + + public static readonly StatDef goldCollected; + + public static readonly StatDef maxGoldCollected; + + public static readonly StatDef totalDistanceTraveled; + + public static readonly StatDef totalItemsCollected; + + public static readonly StatDef highestItemsCollected; + + public static readonly StatDef totalStagesCompleted; + + public static readonly StatDef highestStagesCompleted; + + public static readonly StatDef highestInfiniteTowerWaveReached; + + public static readonly StatDef totalPurchases; + + public static readonly StatDef highestPurchases; + + public static readonly StatDef totalGoldPurchases; + + public static readonly StatDef highestGoldPurchases; + + public static readonly StatDef totalBloodPurchases; + + public static readonly StatDef highestBloodPurchases; + + public static readonly StatDef totalLunarPurchases; + + public static readonly StatDef highestLunarPurchases; + + public static readonly StatDef totalTier1Purchases; + + public static readonly StatDef highestTier1Purchases; + + public static readonly StatDef totalTier2Purchases; + + public static readonly StatDef highestTier2Purchases; + + public static readonly StatDef totalTier3Purchases; + + public static readonly StatDef highestTier3Purchases; + + public static readonly StatDef totalDronesPurchased; + + public static readonly StatDef totalTurretsPurchased; + + public static readonly StatDef totalGreenSoupsPurchased; + + public static readonly StatDef totalRedSoupsPurchased; + + public static readonly StatDef suicideHermitCrabsAchievementProgress; + + public static readonly StatDef firstTeleporterCompleted; + + public static readonly StatDef totalEliteKills; + + public static readonly StatDef totalBurnDeaths; + + public static readonly StatDef totalDeathsWhileBurning; + + public static readonly StatDef totalTeleporterBossKillsWitnessed; + + public static readonly StatDef totalCrocoInfectionsInflicted; + + public static readonly StatDef totalCrocoWeakEnemyKills; + + public static readonly StatDef totalMaulingRockKills; + + public static readonly StatDef chefAlternateSpecialBarbecueBisonAchievementProgress; + + private static string[] bodyNames; + + [CanBeNull] + public static StatDef Find(string statName) + { + nameToStatDef.TryGetValue(statName, out var value); + return value; + } + + private StatDef(string name, StatRecordType recordType, StatDataType dataType, double pointValue, DisplayValueFormatterDelegate displayValueFormatter) + { + this.name = name; + this.recordType = recordType; + this.dataType = dataType; + this.pointValue = pointValue; + this.displayValueFormatter = displayValueFormatter; + displayToken = "STATNAME_" + name.ToUpper(CultureInfo.InvariantCulture); + } + + static StatDef() + { + allStatDefs = new List(); + nameToStatDef = new Dictionary(); + totalGamesPlayed = Register("totalGamesPlayed", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalTimeAlive = Register("totalTimeAlive", StatRecordType.Sum, StatDataType.Double, 1.0, TimeMMSSDisplayValueFormatter); + totalKills = Register("totalKills", StatRecordType.Sum, StatDataType.ULong, 10.0); + totalMinionKills = Register("totalMinionKills", StatRecordType.Sum, StatDataType.ULong, 10.0); + totalDeaths = Register("totalDeaths", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalDamageDealt = Register("totalDamageDealt", StatRecordType.Sum, StatDataType.ULong, 0.01); + totalMinionDamageDealt = Register("totalMinionDamageDealt", StatRecordType.Sum, StatDataType.ULong, 0.01); + totalDamageTaken = Register("totalDamageTaken", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalHealthHealed = Register("totalHealthHealed", StatRecordType.Sum, StatDataType.ULong, 0.01); + highestDamageDealt = Register("highestDamageDealt", StatRecordType.Max, StatDataType.ULong, 1.0); + highestLevel = Register("highestLevel", StatRecordType.Max, StatDataType.ULong, 100.0); + goldCollected = Register("totalGoldCollected", StatRecordType.Sum, StatDataType.ULong, 1.0); + maxGoldCollected = Register("maxGoldCollected", StatRecordType.Max, StatDataType.ULong, 0.0); + totalDistanceTraveled = Register("totalDistanceTraveled", StatRecordType.Sum, StatDataType.Double, 0.01, DistanceMarathonsDisplayValueFormatter); + totalItemsCollected = Register("totalItemsCollected", StatRecordType.Sum, StatDataType.ULong, 110.0); + highestItemsCollected = Register("highestItemsCollected", StatRecordType.Max, StatDataType.ULong, 10.0); + totalStagesCompleted = Register("totalStagesCompleted", StatRecordType.Sum, StatDataType.ULong, 100.0); + highestStagesCompleted = Register("highestStagesCompleted", StatRecordType.Max, StatDataType.ULong, 0.0); + highestInfiniteTowerWaveReached = Register("highestInfiniteTowerWaveReached", StatRecordType.Max, StatDataType.ULong, 100.0); + totalPurchases = Register("totalPurchases", StatRecordType.Sum, StatDataType.ULong, 35.0); + highestPurchases = Register("highestPurchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalGoldPurchases = Register("totalGoldPurchases", StatRecordType.Sum, StatDataType.ULong, 0.0); + highestGoldPurchases = Register("highestGoldPurchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalBloodPurchases = Register("totalBloodPurchases", StatRecordType.Sum, StatDataType.ULong, 0.0); + highestBloodPurchases = Register("highestBloodPurchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalLunarPurchases = Register("totalLunarPurchases", StatRecordType.Sum, StatDataType.ULong, 0.0); + highestLunarPurchases = Register("highestLunarPurchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalTier1Purchases = Register("totalTier1Purchases", StatRecordType.Sum, StatDataType.ULong, 0.0); + highestTier1Purchases = Register("highestTier1Purchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalTier2Purchases = Register("totalTier2Purchases", StatRecordType.Sum, StatDataType.ULong, 0.0); + highestTier2Purchases = Register("highestTier2Purchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalTier3Purchases = Register("totalTier3Purchases", StatRecordType.Sum, StatDataType.ULong, 0.0); + highestTier3Purchases = Register("highestTier3Purchases", StatRecordType.Max, StatDataType.ULong, 0.0); + totalDronesPurchased = Register("totalDronesPurchased", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalTurretsPurchased = Register("totalTurretsPurchased", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalGreenSoupsPurchased = Register("totalGreenSoupsPurchased", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalRedSoupsPurchased = Register("totalRedSoupsPurchased", StatRecordType.Sum, StatDataType.ULong, 0.0); + suicideHermitCrabsAchievementProgress = Register("suicideHermitCrabsAchievementProgress", StatRecordType.Sum, StatDataType.ULong, 0.0); + firstTeleporterCompleted = Register("firstTeleporterCompleted", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalEliteKills = Register("totalEliteKills", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalBurnDeaths = Register("totalBurnDeaths", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalDeathsWhileBurning = Register("totalDeathsWhileBurning", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalTeleporterBossKillsWitnessed = Register("totalTeleporterBossKillsWitnessed", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalCrocoInfectionsInflicted = Register("totalCrocoInfectionsInflicted", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalCrocoWeakEnemyKills = Register("totalCrocoWeakEnemyKills", StatRecordType.Sum, StatDataType.ULong, 0.0); + totalMaulingRockKills = Register("totalMaulingRockKills", StatRecordType.Sum, StatDataType.ULong, 0.0); + chefAlternateSpecialBarbecueBisonAchievementProgress = Register("chefAlternateSpecialBarbecueBisonAchievementProgress", StatRecordType.Sum, StatDataType.ULong, 0.0); + } + + [SystemInitializer(new Type[] + { + typeof(BodyCatalog), + typeof(ItemCatalog), + typeof(EquipmentCatalog), + typeof(SceneCatalog) + })] + private static void Init() + { + PerBodyStatDef.RegisterStatDefs(); + PerItemStatDef.RegisterStatDefs(); + PerEquipmentStatDef.RegisterStatDefs(); + PerStageStatDef.RegisterStatDefs(); + } + + public static StatDef Register(string name, StatRecordType recordType, StatDataType dataType, double pointValue, DisplayValueFormatterDelegate displayValueFormatter = null) + { + if (displayValueFormatter == null) + { + displayValueFormatter = DefaultDisplayValueFormatter; + } + StatDef statDef = new StatDef(name, recordType, dataType, pointValue, displayValueFormatter) + { + index = allStatDefs.Count + }; + allStatDefs.Add(statDef); + nameToStatDef.Add(statDef.name, statDef); + return statDef; + } + + public static string DefaultDisplayValueFormatter(ref StatField statField) + { + return statField.ToLocalNumeric(); + } + + public static string TimeMMSSDisplayValueFormatter(ref StatField statField) + { + ulong num = 0uL; + num = statField.dataType switch + { + StatDataType.ULong => statField.GetULongValue(), + StatDataType.Double => (ulong)statField.GetDoubleValue(), + _ => throw new ArgumentOutOfRangeException(), + }; + ulong num2 = num / 60; + ulong num3 = num - num2 * 60; + return $"{num2:00}:{num3:00}"; + } + + public static string DistanceMarathonsDisplayValueFormatter(ref StatField statField) + { + double num = 0.0; + return string.Format(arg0: statField.dataType switch + { + StatDataType.ULong => statField.GetULongValue(), + StatDataType.Double => statField.GetDoubleValue(), + _ => throw new ArgumentOutOfRangeException(), + } * 2.3699E-05, format: Language.GetString("STAT_VALUE_MARATHONS_FORMAT")); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatEvent.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatEvent.cs new file mode 100644 index 0000000..554638e --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatEvent.cs @@ -0,0 +1,20 @@ +namespace RoR2.Stats; + +public struct StatEvent +{ + public enum Type + { + Damage, + Kill, + Walk, + Die, + Lose, + Win + } + + public string stringValue; + + public double doubleValue; + + public ulong ulongValue; +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatField.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatField.cs new file mode 100644 index 0000000..9a12f83 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatField.cs @@ -0,0 +1,408 @@ +using System; +using System.Runtime.InteropServices; +using JetBrains.Annotations; +using UnityEngine.Networking; + +namespace RoR2.Stats; + +public struct StatField : IComparable +{ + [StructLayout(LayoutKind.Explicit)] + private struct ValueUnion + { + [FieldOffset(0)] + public readonly ulong ulongValue; + + [FieldOffset(0)] + public readonly double doubleValue; + + public static explicit operator ulong(ValueUnion v) + { + return v.ulongValue; + } + + public static explicit operator double(ValueUnion v) + { + return v.doubleValue; + } + + public static implicit operator ValueUnion(ulong ulongValue) + { + return new ValueUnion(ulongValue); + } + + public static implicit operator ValueUnion(double doubleValue) + { + return new ValueUnion(doubleValue); + } + + private ValueUnion(ulong ulongValue) + { + this = default(ValueUnion); + this.ulongValue = ulongValue; + } + + private ValueUnion(double doubleValue) + { + this = default(ValueUnion); + this.doubleValue = doubleValue; + } + } + + public StatDef statDef; + + public bool hasChanged; + + public bool nonDefaultValue; + + private ValueUnion value; + + public string name => statDef.name; + + public StatRecordType recordType => statDef.recordType; + + public StatDataType dataType => statDef.dataType; + + private ulong ulongValue + { + get + { + return value.ulongValue; + } + set + { + this.value = value; + } + } + + private double doubleValue + { + get + { + return value.doubleValue; + } + set + { + this.value = value; + } + } + + public override string ToString() + { + return dataType switch + { + StatDataType.ULong => TextSerialization.ToStringInvariant(value.ulongValue), + StatDataType.Double => TextSerialization.ToStringInvariant(value.doubleValue), + _ => throw new ArgumentOutOfRangeException(), + }; + } + + public string ToLocalNumeric() + { + return dataType switch + { + StatDataType.ULong => TextSerialization.ToStringNumeric(value.ulongValue), + StatDataType.Double => TextSerialization.ToStringNumeric(value.doubleValue), + _ => throw new ArgumentOutOfRangeException(), + }; + } + + public ulong CalculatePointValue() + { + throw new NotImplementedException(); + } + + [Pure] + public static StatField GetDelta(ref StatField newerValue, ref StatField olderValue) + { + StatField result; + if (newerValue.recordType != 0) + { + if (newerValue.dataType == StatDataType.ULong && newerValue.ulongValue == olderValue.ulongValue) + { + result = default(StatField); + result.statDef = newerValue.statDef; + result.hasChanged = false; + result.ulongValue = newerValue.ulongValue; + return result; + } + if (newerValue.dataType == StatDataType.Double && newerValue.doubleValue == olderValue.doubleValue) + { + result = default(StatField); + result.statDef = newerValue.statDef; + result.hasChanged = false; + result.doubleValue = newerValue.doubleValue; + return result; + } + } + result = default(StatField); + result.statDef = newerValue.statDef; + result.hasChanged = false; + StatField result2 = result; + switch (newerValue.dataType) + { + case StatDataType.ULong: + switch (newerValue.recordType) + { + case StatRecordType.Sum: + result2.ulongValue = newerValue.ulongValue - olderValue.ulongValue; + result2.hasChanged = result2.ulongValue != 0; + break; + case StatRecordType.Max: + result2.ulongValue = Math.Max(newerValue.ulongValue, olderValue.ulongValue); + result2.hasChanged = result2.ulongValue != olderValue.ulongValue; + break; + case StatRecordType.Newest: + result2.ulongValue = newerValue.ulongValue; + result2.hasChanged = result2.ulongValue != olderValue.ulongValue; + break; + } + break; + case StatDataType.Double: + switch (newerValue.recordType) + { + case StatRecordType.Sum: + result2.doubleValue = newerValue.doubleValue - olderValue.doubleValue; + result2.hasChanged = result2.doubleValue != 0.0; + break; + case StatRecordType.Max: + result2.doubleValue = Math.Max(newerValue.doubleValue, olderValue.doubleValue); + result2.hasChanged = result2.doubleValue != olderValue.doubleValue; + break; + case StatRecordType.Newest: + result2.doubleValue = newerValue.doubleValue; + result2.hasChanged = result2.doubleValue != olderValue.doubleValue; + break; + } + break; + } + return result2; + } + + public void PushDelta(ref StatField deltaField) + { + switch (dataType) + { + case StatDataType.ULong: + PushStatValue(deltaField.ulongValue); + break; + case StatDataType.Double: + PushStatValue(deltaField.doubleValue); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + public void Write(NetworkWriter writer) + { + switch (dataType) + { + case StatDataType.ULong: + writer.WritePackedUInt64(ulongValue); + break; + case StatDataType.Double: + writer.Write(doubleValue); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + public void Read(NetworkReader reader) + { + switch (dataType) + { + case StatDataType.ULong: + { + ulong num2 = ulongValue; + ulongValue = reader.ReadPackedUInt64(); + hasChanged = ulongValue != num2; + break; + } + case StatDataType.Double: + { + double num = doubleValue; + doubleValue = reader.ReadDouble(); + hasChanged = num != doubleValue; + break; + } + default: + throw new ArgumentOutOfRangeException(); + } + } + + private void EnforceDataType(StatDataType otherDataType) + { + if (dataType != otherDataType) + { + throw new InvalidOperationException($"Expected data type {dataType}, got data type {otherDataType}."); + } + } + + public void PushStatValue(ulong incomingValue) + { + EnforceDataType(StatDataType.ULong); + switch (recordType) + { + case StatRecordType.Sum: + ulongValue += incomingValue; + break; + case StatRecordType.Max: + ulongValue = Math.Max(incomingValue, ulongValue); + break; + case StatRecordType.Newest: + ulongValue = incomingValue; + break; + } + hasChanged = true; + nonDefaultValue = ulongValue != 0; + } + + public void PushStatValue(double incomingValue) + { + EnforceDataType(StatDataType.Double); + switch (recordType) + { + case StatRecordType.Sum: + doubleValue += incomingValue; + break; + case StatRecordType.Max: + doubleValue = Math.Max(incomingValue, doubleValue); + break; + case StatRecordType.Newest: + doubleValue = incomingValue; + break; + } + hasChanged = true; + nonDefaultValue = doubleValue != 0.0; + } + + public void SetFromString(string valueString) + { + switch (dataType) + { + case StatDataType.ULong: + { + TextSerialization.TryParseInvariant(valueString, out ulong result2); + value = result2; + nonDefaultValue = ulongValue != 0; + hasChanged = true; + break; + } + case StatDataType.Double: + { + TextSerialization.TryParseInvariant(valueString, out double result); + value = result; + nonDefaultValue = doubleValue != 0.0; + hasChanged = true; + break; + } + default: + throw new ArgumentOutOfRangeException(); + } + } + + public ulong GetULongValue() + { + EnforceDataType(StatDataType.ULong); + return ulongValue; + } + + public double GetDoubleValue() + { + EnforceDataType(StatDataType.Double); + return doubleValue; + } + + public double GetValueAsDouble() + { + return dataType switch + { + StatDataType.ULong => ulongValue, + StatDataType.Double => doubleValue, + _ => throw new ArgumentOutOfRangeException(), + }; + } + + [Obsolete] + public decimal GetDecimalValue() + { + return dataType switch + { + StatDataType.ULong => ulongValue, + StatDataType.Double => (decimal)doubleValue, + _ => throw new ArgumentOutOfRangeException(), + }; + } + + public bool IsDefault() + { + return dataType switch + { + StatDataType.ULong => ulongValue == 0, + StatDataType.Double => doubleValue == 0.0, + _ => true, + }; + } + + public void SetDefault() + { + switch (dataType) + { + case StatDataType.ULong: + ulongValue = 0uL; + break; + case StatDataType.Double: + doubleValue = 0.0; + break; + default: + throw new NotImplementedException(); + } + nonDefaultValue = false; + hasChanged = false; + } + + public ulong GetPointValue(double pointValue) + { + return dataType switch + { + StatDataType.ULong => (ulong)((double)ulongValue * pointValue), + StatDataType.Double => (ulong)(doubleValue * pointValue), + _ => throw new ArgumentOutOfRangeException(), + }; + } + + public int CompareTo(StatField other) + { + return CompareTo(in other); + } + + public int CompareTo(in StatField other) + { + EnforceDataType(other.dataType); + return dataType switch + { + StatDataType.ULong => ulongValue.CompareTo(other.ulongValue), + StatDataType.Double => doubleValue.CompareTo(other.doubleValue), + _ => throw new ArgumentOutOfRangeException(), + }; + } + + public void SetToMaxValue() + { + switch (dataType) + { + case StatDataType.ULong: + ulongValue = ulong.MaxValue; + break; + case StatDataType.Double: + doubleValue = double.MaxValue; + break; + default: + throw new ArgumentOutOfRangeException(); + } + nonDefaultValue = true; + hasChanged = true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatManager.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatManager.cs new file mode 100644 index 0000000..30304d7 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatManager.cs @@ -0,0 +1,604 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.Stats; + +internal class StatManager +{ + private struct DamageEvent + { + [CanBeNull] + public CharacterMaster attackerMaster; + + public BodyIndex attackerBodyIndex; + + [CanBeNull] + public CharacterMaster attackerOwnerMaster; + + public BodyIndex attackerOwnerBodyIndex; + + [CanBeNull] + public CharacterMaster victimMaster; + + public BodyIndex victimBodyIndex; + + public bool victimIsElite; + + public float damageDealt; + + public DotController.DotIndex dotType; + } + + private struct DeathEvent + { + public DamageReport damageReport; + + public bool victimWasBurning; + } + + private struct HealingEvent + { + [CanBeNull] + public GameObject healee; + + public float healAmount; + } + + private struct GoldEvent + { + [CanBeNull] + public CharacterMaster characterMaster; + + public ulong amount; + } + + [StructLayout(LayoutKind.Sequential, Size = 1)] + private struct PurchaseStatEvent + { + } + + public struct CharacterUpdateEvent + { + public PlayerStatsComponent statsComponent; + + public float additionalDistanceTraveled; + + public float additionalTimeAlive; + + public int level; + + public float runTime; + } + + private struct ItemCollectedEvent + { + [CanBeNull] + public Inventory inventory; + + public ItemIndex itemIndex; + + public int quantity; + + public int newCount; + } + + private static BodyIndex crocoBodyIndex = BodyIndex.None; + + private static readonly Queue damageEvents = new Queue(); + + private static readonly Queue deathEvents = new Queue(); + + private static readonly Queue healingEvents = new Queue(); + + private static readonly Queue goldCollectedEvents = new Queue(); + + private static readonly Queue purchaseStatEvents = new Queue(); + + private static readonly Queue characterUpdateEvents = new Queue(); + + private static readonly Queue itemCollectedEvents = new Queue(); + + [SystemInitializer(new Type[] + { + typeof(BodyCatalog), + typeof(ItemCatalog), + typeof(EquipmentCatalog), + typeof(PickupCatalog) + })] + private static void Init() + { + GlobalEventManager.onServerDamageDealt += OnDamageDealt; + GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; + GlobalEventManager.onServerCharacterExecuted += OnCharacterExecute; + HealthComponent.onCharacterHealServer += OnCharacterHeal; + Run.onPlayerFirstCreatedServer += OnPlayerFirstCreatedServer; + Run.onServerGameOver += OnServerGameOver; + Stage.onServerStageComplete += OnServerStageComplete; + Stage.onServerStageBegin += OnServerStageBegin; + Inventory.onServerItemGiven += OnServerItemGiven; + RoR2Application.onFixedUpdate += ProcessEvents; + EquipmentSlot.onServerEquipmentActivated += OnEquipmentActivated; + InfiniteTowerRun.onWaveInitialized += OnInfiniteTowerWaveInitialized; + crocoBodyIndex = BodyCatalog.FindBodyIndex("CrocoBody"); + } + + private static void OnInfiniteTowerWaveInitialized(InfiniteTowerWaveController waveController) + { + ulong statValue = (ulong)((Run.instance as InfiniteTowerRun)?.waveIndex ?? 0); + foreach (PlayerStatsComponent instances in PlayerStatsComponent.instancesList) + { + if (!instances.playerCharacterMasterController.isConnected) + { + continue; + } + PerBodyStatDef perBodyStatDef = null; + switch (Run.instance.selectedDifficulty) + { + case DifficultyIndex.Easy: + perBodyStatDef = PerBodyStatDef.highestInfiniteTowerWaveReachedEasy; + break; + case DifficultyIndex.Normal: + perBodyStatDef = PerBodyStatDef.highestInfiniteTowerWaveReachedNormal; + break; + case DifficultyIndex.Hard: + perBodyStatDef = PerBodyStatDef.highestInfiniteTowerWaveReachedHard; + break; + } + StatSheet currentStats = instances.currentStats; + currentStats.PushStatValue(StatDef.highestInfiniteTowerWaveReached, statValue); + if (perBodyStatDef != null) + { + CharacterBody body = instances.characterMaster.GetBody(); + if ((bool)body) + { + string bodyName = BodyCatalog.GetBodyName(body.bodyIndex); + currentStats.PushStatValue(perBodyStatDef.FindStatDef(bodyName ?? ""), statValue); + } + } + } + } + + private static void OnServerGameOver(Run run, GameEndingDef gameEndingDef) + { + if (!gameEndingDef.isWin || !(run.GetType() == typeof(Run))) + { + return; + } + foreach (PlayerStatsComponent instances in PlayerStatsComponent.instancesList) + { + if (instances.playerCharacterMasterController.isConnected) + { + instances.currentStats.PushStatValue(PerBodyStatDef.totalWins.FindStatDef(instances.characterMaster.bodyPrefab?.name ?? ""), 1uL); + } + } + } + + private static void OnPlayerFirstCreatedServer(Run run, PlayerCharacterMasterController playerCharacterMasterController) + { + playerCharacterMasterController.master.onBodyStart += OnBodyFirstStart; + } + + private static void OnBodyFirstStart(CharacterBody body) + { + CharacterMaster master = body.master; + if (!master) + { + return; + } + master.onBodyStart -= OnBodyFirstStart; + PlayerCharacterMasterController component = master.GetComponent(); + if ((bool)component) + { + PlayerStatsComponent component2 = component.GetComponent(); + if ((bool)component2) + { + StatSheet currentStats = component2.currentStats; + currentStats.PushStatValue(PerBodyStatDef.timesPicked.FindStatDef(body.name), 1uL); + currentStats.PushStatValue(StatDef.totalGamesPlayed, 1uL); + } + } + } + + public static void ForceUpdate() + { + ProcessEvents(); + } + + private static void ProcessEvents() + { + ProcessDamageEvents(); + ProcessDeathEvents(); + ProcessHealingEvents(); + ProcessGoldEvents(); + ProcessItemCollectedEvents(); + ProcessCharacterUpdateEvents(); + } + + public static void OnCharacterHeal(HealthComponent healthComponent, float amount, ProcChainMask procChainMask) + { + healingEvents.Enqueue(new HealingEvent + { + healee = healthComponent.gameObject, + healAmount = amount + }); + } + + public static void OnDamageDealt(DamageReport damageReport) + { + damageEvents.Enqueue(new DamageEvent + { + attackerMaster = damageReport.attackerMaster, + attackerBodyIndex = damageReport.attackerBodyIndex, + attackerOwnerMaster = damageReport.attackerOwnerMaster, + attackerOwnerBodyIndex = damageReport.attackerOwnerBodyIndex, + victimMaster = damageReport.victimMaster, + victimBodyIndex = damageReport.victimBodyIndex, + victimIsElite = damageReport.victimIsElite, + damageDealt = damageReport.damageDealt, + dotType = damageReport.dotType + }); + } + + public static void OnCharacterExecute(DamageReport damageReport, float executionHealthLost) + { + damageEvents.Enqueue(new DamageEvent + { + attackerMaster = damageReport.attackerMaster, + attackerBodyIndex = damageReport.attackerBodyIndex, + attackerOwnerMaster = damageReport.attackerOwnerMaster, + attackerOwnerBodyIndex = damageReport.attackerOwnerBodyIndex, + victimMaster = damageReport.victimMaster, + victimBodyIndex = damageReport.victimBodyIndex, + victimIsElite = damageReport.victimIsElite, + damageDealt = executionHealthLost, + dotType = damageReport.dotType + }); + } + + public static void OnCharacterDeath(DamageReport damageReport) + { + DotController dotController = DotController.FindDotController(damageReport.victim.gameObject); + bool victimWasBurning = false; + if ((bool)dotController) + { + victimWasBurning = dotController.HasDotActive(DotController.DotIndex.Burn) | dotController.HasDotActive(DotController.DotIndex.PercentBurn) | dotController.HasDotActive(DotController.DotIndex.Helfire) | dotController.HasDotActive(DotController.DotIndex.StrongerBurn); + } + deathEvents.Enqueue(new DeathEvent + { + damageReport = damageReport, + victimWasBurning = victimWasBurning + }); + } + + private static void ProcessHealingEvents() + { + while (healingEvents.Count > 0) + { + HealingEvent healingEvent = healingEvents.Dequeue(); + ulong statValue = (ulong)healingEvent.healAmount; + PlayerStatsComponent.FindBodyStatSheet(healingEvent.healee)?.PushStatValue(StatDef.totalHealthHealed, statValue); + } + } + + private static void ProcessDamageEvents() + { + while (damageEvents.Count > 0) + { + DamageEvent damageEvent = damageEvents.Dequeue(); + ulong statValue = (ulong)damageEvent.damageDealt; + StatSheet statSheet = PlayerStatsComponent.FindMasterStatSheet(damageEvent.victimMaster); + StatSheet statSheet2 = PlayerStatsComponent.FindMasterStatSheet(damageEvent.attackerMaster); + StatSheet statSheet3 = PlayerStatsComponent.FindMasterStatSheet(damageEvent.attackerOwnerMaster); + if (statSheet != null) + { + statSheet.PushStatValue(StatDef.totalDamageTaken, statValue); + if (damageEvent.attackerBodyIndex != BodyIndex.None) + { + statSheet.PushStatValue(PerBodyStatDef.damageTakenFrom, damageEvent.attackerBodyIndex, statValue); + } + if (damageEvent.victimBodyIndex != BodyIndex.None) + { + statSheet.PushStatValue(PerBodyStatDef.damageTakenAs, damageEvent.victimBodyIndex, statValue); + } + } + if (statSheet2 != null) + { + statSheet2.PushStatValue(StatDef.totalDamageDealt, statValue); + statSheet2.PushStatValue(StatDef.highestDamageDealt, statValue); + if (damageEvent.attackerBodyIndex != BodyIndex.None) + { + statSheet2.PushStatValue(PerBodyStatDef.damageDealtAs, damageEvent.attackerBodyIndex, statValue); + } + if (damageEvent.victimBodyIndex != BodyIndex.None) + { + statSheet2.PushStatValue(PerBodyStatDef.damageDealtTo, damageEvent.victimBodyIndex, statValue); + } + } + if (statSheet3 != null) + { + statSheet3.PushStatValue(StatDef.totalMinionDamageDealt, statValue); + if (damageEvent.attackerOwnerBodyIndex != BodyIndex.None) + { + statSheet3.PushStatValue(PerBodyStatDef.minionDamageDealtAs, damageEvent.attackerOwnerBodyIndex, statValue); + } + } + } + } + + private static void ProcessDeathEvents() + { + while (deathEvents.Count > 0) + { + DeathEvent deathEvent = deathEvents.Dequeue(); + DamageReport damageReport = deathEvent.damageReport; + StatSheet statSheet = PlayerStatsComponent.FindMasterStatSheet(damageReport.victimMaster); + StatSheet statSheet2 = PlayerStatsComponent.FindMasterStatSheet(damageReport.attackerMaster); + StatSheet statSheet3 = PlayerStatsComponent.FindMasterStatSheet(damageReport.attackerOwnerMaster); + if (statSheet != null) + { + statSheet.PushStatValue(StatDef.totalDeaths, 1uL); + statSheet.PushStatValue(PerBodyStatDef.deathsAs, damageReport.victimBodyIndex, 1uL); + if (damageReport.attackerBodyIndex != BodyIndex.None) + { + statSheet.PushStatValue(PerBodyStatDef.deathsFrom, damageReport.attackerBodyIndex, 1uL); + } + if (damageReport.dotType != DotController.DotIndex.None) + { + DotController.DotIndex dotType = damageReport.dotType; + if ((uint)(dotType - 1) <= 2u || dotType == DotController.DotIndex.StrongerBurn) + { + statSheet.PushStatValue(StatDef.totalBurnDeaths, 1uL); + } + } + if (deathEvent.victimWasBurning) + { + statSheet.PushStatValue(StatDef.totalDeathsWhileBurning, 1uL); + } + } + if (statSheet2 != null) + { + statSheet2.PushStatValue(StatDef.totalKills, 1uL); + statSheet2.PushStatValue(PerBodyStatDef.killsAs, damageReport.attackerBodyIndex, 1uL); + if (damageReport.victimBodyIndex != BodyIndex.None) + { + statSheet2.PushStatValue(PerBodyStatDef.killsAgainst, damageReport.victimBodyIndex, 1uL); + if (damageReport.victimIsElite) + { + statSheet2.PushStatValue(StatDef.totalEliteKills, 1uL); + statSheet2.PushStatValue(PerBodyStatDef.killsAgainstElite, damageReport.victimBodyIndex, 1uL); + } + } + if (damageReport.attackerBodyIndex == crocoBodyIndex && damageReport.combinedHealthBeforeDamage <= 1f) + { + statSheet2.PushStatValue(StatDef.totalCrocoWeakEnemyKills, 1uL); + } + string text = damageReport.victimBody?.customKillTotalStatName; + if (!string.IsNullOrEmpty(text)) + { + StatDef statDef = StatDef.Find(text); + if (statDef == null) + { + Debug.LogWarningFormat("Stat def \"{0}\" could not be found.", text); + } + else + { + statSheet2.PushStatValue(statDef, 1uL); + } + } + } + if (statSheet3 != null) + { + statSheet3.PushStatValue(StatDef.totalMinionKills, 1uL); + if (damageReport.attackerOwnerBodyIndex != BodyIndex.None) + { + statSheet3.PushStatValue(PerBodyStatDef.minionKillsAs, damageReport.attackerOwnerBodyIndex, 1uL); + } + } + if (!damageReport.victimIsBoss) + { + continue; + } + int i = 0; + for (int count = PlayerStatsComponent.instancesList.Count; i < count; i++) + { + PlayerStatsComponent playerStatsComponent = PlayerStatsComponent.instancesList[i]; + if (playerStatsComponent.characterMaster.hasBody) + { + playerStatsComponent.currentStats.PushStatValue(StatDef.totalTeleporterBossKillsWitnessed, 1uL); + } + } + } + } + + public static void OnGoldCollected(CharacterMaster characterMaster, ulong amount) + { + goldCollectedEvents.Enqueue(new GoldEvent + { + characterMaster = characterMaster, + amount = amount + }); + } + + private static void ProcessGoldEvents() + { + while (goldCollectedEvents.Count > 0) + { + GoldEvent goldEvent = goldCollectedEvents.Dequeue(); + StatSheet statSheet = goldEvent.characterMaster?.GetComponent()?.currentStats; + if (statSheet != null) + { + statSheet.PushStatValue(StatDef.goldCollected, goldEvent.amount); + statSheet.PushStatValue(StatDef.maxGoldCollected, statSheet.GetStatValueULong(StatDef.goldCollected)); + } + } + } + + public static void OnPurchase(CharacterBody characterBody, CostTypeIndex costType, T statDefsToIncrement) where T : IEnumerable + { + StatSheet statSheet = PlayerStatsComponent.FindBodyStatSheet(characterBody); + if (statSheet == null) + { + return; + } + StatDef statDef = null; + StatDef statDef2 = null; + switch (costType) + { + case CostTypeIndex.Money: + statDef = StatDef.totalGoldPurchases; + statDef2 = StatDef.highestGoldPurchases; + break; + case CostTypeIndex.PercentHealth: + statDef = StatDef.totalBloodPurchases; + statDef2 = StatDef.highestBloodPurchases; + break; + case CostTypeIndex.LunarCoin: + statDef = StatDef.totalLunarPurchases; + statDef2 = StatDef.highestLunarPurchases; + break; + case CostTypeIndex.WhiteItem: + statDef = StatDef.totalTier1Purchases; + statDef2 = StatDef.highestTier1Purchases; + break; + case CostTypeIndex.GreenItem: + statDef = StatDef.totalTier2Purchases; + statDef2 = StatDef.highestTier2Purchases; + break; + case CostTypeIndex.RedItem: + statDef = StatDef.totalTier3Purchases; + statDef2 = StatDef.highestTier3Purchases; + break; + } + statSheet.PushStatValue(StatDef.totalPurchases, 1uL); + statSheet.PushStatValue(StatDef.highestPurchases, statSheet.GetStatValueULong(StatDef.totalPurchases)); + if (statDef != null) + { + statSheet.PushStatValue(statDef, 1uL); + if (statDef2 != null) + { + statSheet.PushStatValue(statDef2, statSheet.GetStatValueULong(statDef)); + } + } + if (statDefsToIncrement == null) + { + return; + } + foreach (StatDef item in statDefsToIncrement) + { + if (item != null) + { + statSheet.PushStatValue(item, 1uL); + } + } + } + + public static void OnEquipmentActivated(EquipmentSlot activator, EquipmentIndex equipmentIndex) + { + PlayerStatsComponent.FindBodyStatSheet(activator.characterBody)?.PushStatValue(PerEquipmentStatDef.totalTimesFired.FindStatDef(equipmentIndex), 1uL); + } + + public static void PushCharacterUpdateEvent(CharacterUpdateEvent e) + { + characterUpdateEvents.Enqueue(e); + } + + private static void ProcessCharacterUpdateEvents() + { + while (characterUpdateEvents.Count > 0) + { + CharacterUpdateEvent characterUpdateEvent = characterUpdateEvents.Dequeue(); + if (!characterUpdateEvent.statsComponent) + { + continue; + } + StatSheet currentStats = characterUpdateEvent.statsComponent.currentStats; + if (currentStats != null) + { + BodyIndex bodyIndex = characterUpdateEvent.statsComponent.characterMaster.GetBody()?.bodyIndex ?? BodyIndex.None; + currentStats.PushStatValue(StatDef.totalTimeAlive, characterUpdateEvent.additionalTimeAlive); + currentStats.PushStatValue(StatDef.highestLevel, (ulong)characterUpdateEvent.level); + currentStats.PushStatValue(StatDef.totalDistanceTraveled, characterUpdateEvent.additionalDistanceTraveled); + if (bodyIndex != BodyIndex.None) + { + currentStats.PushStatValue(PerBodyStatDef.totalTimeAlive, bodyIndex, characterUpdateEvent.additionalTimeAlive); + currentStats.PushStatValue(PerBodyStatDef.longestRun, bodyIndex, characterUpdateEvent.runTime); + } + EquipmentIndex currentEquipmentIndex = characterUpdateEvent.statsComponent.characterMaster.inventory.currentEquipmentIndex; + if (currentEquipmentIndex != EquipmentIndex.None) + { + currentStats.PushStatValue(PerEquipmentStatDef.totalTimeHeld.FindStatDef(currentEquipmentIndex), characterUpdateEvent.additionalTimeAlive); + } + } + } + } + + private static void OnServerItemGiven(Inventory inventory, ItemIndex itemIndex, int quantity) + { + itemCollectedEvents.Enqueue(new ItemCollectedEvent + { + inventory = inventory, + itemIndex = itemIndex, + quantity = quantity, + newCount = inventory.GetItemCount(itemIndex) + }); + } + + private static void ProcessItemCollectedEvents() + { + while (itemCollectedEvents.Count > 0) + { + ItemCollectedEvent itemCollectedEvent = itemCollectedEvents.Dequeue(); + if ((bool)itemCollectedEvent.inventory) + { + StatSheet statSheet = itemCollectedEvent.inventory.GetComponent()?.currentStats; + if (statSheet != null) + { + statSheet.PushStatValue(StatDef.totalItemsCollected, (ulong)itemCollectedEvent.quantity); + statSheet.PushStatValue(StatDef.highestItemsCollected, statSheet.GetStatValueULong(StatDef.totalItemsCollected)); + statSheet.PushStatValue(PerItemStatDef.totalCollected.FindStatDef(itemCollectedEvent.itemIndex), (ulong)itemCollectedEvent.quantity); + statSheet.PushStatValue(PerItemStatDef.highestCollected.FindStatDef(itemCollectedEvent.itemIndex), (ulong)itemCollectedEvent.newCount); + } + } + } + } + + private static void OnServerStageBegin(Stage stage) + { + foreach (PlayerStatsComponent instances in PlayerStatsComponent.instancesList) + { + if (instances.playerCharacterMasterController.isConnected) + { + StatSheet currentStats = instances.currentStats; + StatDef statDef = PerStageStatDef.totalTimesVisited.FindStatDef(stage.sceneDef ? stage.sceneDef.baseSceneName : string.Empty); + if (statDef != null) + { + currentStats.PushStatValue(statDef, 1uL); + } + } + } + } + + private static void OnServerStageComplete(Stage stage) + { + foreach (PlayerStatsComponent instances in PlayerStatsComponent.instancesList) + { + if (instances.playerCharacterMasterController.isConnected) + { + StatSheet currentStats = instances.currentStats; + if (SceneInfo.instance.countsAsStage) + { + currentStats.PushStatValue(StatDef.totalStagesCompleted, 1uL); + currentStats.PushStatValue(StatDef.highestStagesCompleted, currentStats.GetStatValueULong(StatDef.totalStagesCompleted)); + } + StatDef statDef = PerStageStatDef.totalTimesCleared.FindStatDef(stage.sceneDef ? stage.sceneDef.baseSceneName : string.Empty); + if (statDef != null) + { + currentStats.PushStatValue(statDef, 1uL); + } + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatRecordType.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatRecordType.cs new file mode 100644 index 0000000..1b4ccb9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatRecordType.cs @@ -0,0 +1,8 @@ +namespace RoR2.Stats; + +public enum StatRecordType +{ + Sum, + Max, + Newest +} diff --git a/ilspy_dump/ror2_csproj/RoR2.Stats/StatSheet.cs b/ilspy_dump/ror2_csproj/RoR2.Stats/StatSheet.cs new file mode 100644 index 0000000..99fbc69 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.Stats/StatSheet.cs @@ -0,0 +1,496 @@ +using System; +using System.Linq; +using System.Xml.Linq; +using HG; +using JetBrains.Annotations; +using UnityEngine.Networking; + +namespace RoR2.Stats; + +public class StatSheet +{ + private static StatField[] fieldsTemplate; + + private static bool[] nonDefaultFieldsBuffer; + + public readonly StatField[] fields; + + private UnlockableIndex[] unlockables = Array.Empty(); + + public void SetStatValueFromString([CanBeNull] StatDef statDef, string value) + { + if (statDef != null) + { + fields[statDef.index].SetFromString(value); + } + } + + public void PushStatValue([CanBeNull] StatDef statDef, ulong statValue) + { + if (statDef != null) + { + int index = statDef.index; + fields[index].PushStatValue(statValue); + } + } + + public void PushStatValue([CanBeNull] StatDef statDef, double statValue) + { + if (statDef != null) + { + fields[statDef.index].PushStatValue(statValue); + } + } + + public void PushStatValue([NotNull] PerBodyStatDef perBodyStatDef, BodyIndex bodyIndex, ulong statValue) + { + PushStatValue(perBodyStatDef.FindStatDef(bodyIndex), statValue); + } + + public void PushStatValue([NotNull] PerBodyStatDef perBodyStatDef, BodyIndex bodyIndex, double statValue) + { + PushStatValue(perBodyStatDef.FindStatDef(bodyIndex), statValue); + } + + public ulong GetStatValueULong([CanBeNull] StatDef statDef) + { + if (statDef == null) + { + return 0uL; + } + return fields[statDef.index].GetULongValue(); + } + + public double GetStatValueDouble([CanBeNull] StatDef statDef) + { + if (statDef == null) + { + return 0.0; + } + return fields[statDef.index].GetDoubleValue(); + } + + public double GetStatValueAsDouble([CanBeNull] StatDef statDef) + { + if (statDef == null) + { + return 0.0; + } + return fields[statDef.index].GetValueAsDouble(); + } + + [Obsolete] + public decimal GetStatValueDecimal([CanBeNull] StatDef statDef) + { + if (statDef == null) + { + return 0m; + } + return fields[statDef.index].GetDecimalValue(); + } + + [NotNull] + public string GetStatValueString([CanBeNull] StatDef statDef) + { + if (statDef == null) + { + return "INVALID_STAT"; + } + return fields[statDef.index].ToString(); + } + + [NotNull] + public string GetStatDisplayValue([CanBeNull] StatDef statDef) + { + if (statDef == null) + { + return "INVALID_STAT"; + } + return statDef.displayValueFormatter(ref fields[statDef.index]); + } + + public ulong GetStatPointValue([NotNull] StatDef statDef) + { + return fields[statDef.index].GetPointValue(statDef.pointValue); + } + + public ulong GetStatValueULong([NotNull] PerBodyStatDef perBodyStatDef, [NotNull] string bodyName) + { + return GetStatValueULong(perBodyStatDef.FindStatDef(bodyName)); + } + + public double GetStatValueDouble([NotNull] PerBodyStatDef perBodyStatDef, [NotNull] string bodyName) + { + return GetStatValueDouble(perBodyStatDef.FindStatDef(bodyName)); + } + + [NotNull] + public string GetStatValueString([NotNull] PerBodyStatDef perBodyStatDef, [NotNull] string bodyName) + { + return GetStatValueString(perBodyStatDef.FindStatDef(bodyName)); + } + + public BodyIndex FindBodyWithHighestStat([NotNull] PerBodyStatDef perBodyStatDef) + { + StatField statField = fields[perBodyStatDef.FindStatDef((BodyIndex)0).index]; + BodyIndex result = (BodyIndex)0; + for (BodyIndex bodyIndex = (BodyIndex)1; (int)bodyIndex < BodyCatalog.bodyCount; bodyIndex++) + { + ref StatField reference = ref fields[perBodyStatDef.FindStatDef(bodyIndex).index]; + if (statField.CompareTo(in reference) < 0) + { + statField = reference; + result = bodyIndex; + } + } + if (statField.IsDefault()) + { + return BodyIndex.None; + } + return result; + } + + public EquipmentIndex FindEquipmentWithHighestStat([NotNull] PerEquipmentStatDef perEquipmentStatDef) + { + StatField statField = fields[perEquipmentStatDef.FindStatDef((EquipmentIndex)0).index]; + EquipmentIndex result = (EquipmentIndex)0; + for (int i = 1; i < EquipmentCatalog.equipmentCount; i++) + { + ref StatField reference = ref fields[perEquipmentStatDef.FindStatDef((EquipmentIndex)i).index]; + if (statField.CompareTo(in reference) < 0) + { + statField = reference; + result = (EquipmentIndex)i; + } + } + if (statField.IsDefault()) + { + return EquipmentIndex.None; + } + return result; + } + + [SystemInitializer(new Type[] { typeof(StatDef) })] + private static void Init() + { + OnFieldsFinalized(); + } + + static StatSheet() + { + HGXml.Register(ToXml, FromXml); + } + + public static void ToXml(XElement element, StatSheet statSheet) + { + element.RemoveAll(); + XElement xElement = new XElement("fields"); + element.Add(xElement); + StatField[] array = statSheet.fields; + for (int i = 0; i < array.Length; i++) + { + ref StatField reference = ref array[i]; + if (!reference.IsDefault()) + { + xElement.Add(new XElement(reference.name, reference.ToString())); + } + } + } + + public static bool FromXml(XElement element, ref StatSheet statSheet) + { + XElement xElement = element.Element("fields"); + if (xElement == null) + { + return false; + } + StatField[] array = statSheet.fields; + for (int i = 0; i < array.Length; i++) + { + ref StatField reference = ref array[i]; + XElement xElement2 = xElement.Element(reference.name); + if (xElement2 != null) + { + reference.SetFromString(xElement2.Value); + } + } + return true; + } + + private static void OnFieldsFinalized() + { + fieldsTemplate = StatDef.allStatDefs.Select(delegate(StatDef v) + { + StatField result = default(StatField); + result.statDef = v; + return result; + }).ToArray(); + nonDefaultFieldsBuffer = new bool[fieldsTemplate.Length]; + PlatformSystems.saveSystem.isXmlReady = true; + } + + private StatSheet([NotNull] StatField[] fields) + { + this.fields = fields; + } + + public static StatSheet New() + { + StatField[] array = new StatField[fieldsTemplate.Length]; + for (int i = 0; i < array.Length; i++) + { + array[i] = fieldsTemplate[i]; + } + return new StatSheet(array); + } + + public int GetUnlockableCount() + { + return unlockables.Length; + } + + public UnlockableIndex GetUnlockableIndex(int index) + { + return unlockables[index]; + } + + public UnlockableDef GetUnlockable(int index) + { + return UnlockableCatalog.GetUnlockableDef(unlockables[index]); + } + + public bool HasUnlockable([CanBeNull] UnlockableDef unlockableDef) + { + if (!unlockableDef || unlockableDef.index == UnlockableIndex.None) + { + return true; + } + for (int i = 0; i < unlockables.Length; i++) + { + if (unlockables[i] == unlockableDef.index) + { + return true; + } + } + return false; + } + + private void AllocateUnlockables(int desiredCount) + { + Array.Resize(ref unlockables, desiredCount); + } + + public void AddUnlockable([NotNull] UnlockableDef unlockableDef) + { + AddUnlockable(unlockableDef.index); + } + + public void AddUnlockable(UnlockableIndex unlockIndex) + { + if (Array.IndexOf(unlockables, unlockIndex) == -1) + { + Array.Resize(ref unlockables, unlockables.Length + 1); + unlockables[unlockables.Length - 1] = unlockIndex; + } + } + + public void RemoveUnlockable(UnlockableIndex unlockIndex) + { + int num = Array.IndexOf(unlockables, unlockIndex); + if (num != -1) + { + int arraySize = unlockables.Length; + ArrayUtils.ArrayRemoveAt(unlockables, ref arraySize, num); + Array.Resize(ref unlockables, arraySize); + } + } + + public void Write(NetworkWriter writer) + { + for (int i = 0; i < fields.Length; i++) + { + nonDefaultFieldsBuffer[i] = fields[i].nonDefaultValue; + } + writer.WriteBitArray(nonDefaultFieldsBuffer); + for (int j = 0; j < fields.Length; j++) + { + if (nonDefaultFieldsBuffer[j]) + { + fields[j].Write(writer); + } + } + writer.Write((byte)unlockables.Length); + for (int k = 0; k < unlockables.Length; k++) + { + writer.Write(unlockables[k]); + } + } + + public void WriteChanges(NetworkWriter writer) + { + for (int i = 0; i < fields.Length; i++) + { + nonDefaultFieldsBuffer[i] = fields[i].hasChanged; + } + writer.WriteBitArray(nonDefaultFieldsBuffer); + for (int j = 0; j < fields.Length; j++) + { + if (nonDefaultFieldsBuffer[j]) + { + fields[j].Write(writer); + } + } + writer.Write((byte)unlockables.Length); + for (int k = 0; k < unlockables.Length; k++) + { + writer.Write(unlockables[k]); + } + } + + public void Read(NetworkReader reader) + { + reader.ReadBitArray(nonDefaultFieldsBuffer); + for (int i = 0; i < fields.Length; i++) + { + if (nonDefaultFieldsBuffer[i]) + { + fields[i].Read(reader); + } + } + int num = reader.ReadByte(); + AllocateUnlockables(num); + for (int j = 0; j < num; j++) + { + unlockables[j] = reader.ReadUnlockableIndex(); + } + } + + public void ReadOrSetDefault(NetworkReader reader) + { + reader.ReadBitArray(nonDefaultFieldsBuffer); + for (int i = 0; i < fields.Length; i++) + { + if (nonDefaultFieldsBuffer[i]) + { + fields[i].Read(reader); + } + else + { + fields[i].SetDefault(); + } + } + int num = reader.ReadByte(); + AllocateUnlockables(num); + for (int j = 0; j < num; j++) + { + unlockables[j] = reader.ReadUnlockableIndex(); + } + } + + public static void GetDelta(StatSheet result, StatSheet newerStats, StatSheet olderStats) + { + StatField[] array = result.fields; + StatField[] array2 = newerStats.fields; + StatField[] array3 = olderStats.fields; + int num = array.Length; + for (int i = 0; i < num; i++) + { + if (!array2[i].hasChanged) + { + array[i].hasChanged = false; + } + else + { + array[i] = StatField.GetDelta(ref array2[i], ref array3[i]); + } + } + UnlockableIndex[] array4 = newerStats.unlockables; + UnlockableIndex[] array5 = olderStats.unlockables; + int num2 = 0; + foreach (UnlockableIndex unlockableIndex in array4) + { + bool flag = false; + for (int k = 0; k < array5.Length; k++) + { + if (array5[k] == unlockableIndex) + { + flag = true; + break; + } + } + if (!flag) + { + num2++; + } + } + result.AllocateUnlockables(num2); + UnlockableIndex[] array6 = result.unlockables; + int num3 = 0; + foreach (UnlockableIndex unlockableIndex2 in array4) + { + bool flag2 = false; + for (int m = 0; m < array5.Length; m++) + { + if (array5[m] == unlockableIndex2) + { + flag2 = true; + break; + } + } + if (!flag2) + { + array6[num3++] = unlockableIndex2; + } + } + } + + public void ApplyDelta(StatSheet deltaSheet) + { + StatField[] array = deltaSheet.fields; + for (int i = 0; i < fields.Length; i++) + { + if (array[i].hasChanged) + { + fields[i].PushDelta(ref array[i]); + fields[i].hasChanged = false; + } + } + for (int j = 0; j < deltaSheet.unlockables.Length; j++) + { + AddUnlockable(deltaSheet.unlockables[j]); + } + } + + public void ClearHasChangedFlags() + { + int num = fields.Length; + for (int i = 0; i < num; i++) + { + fields[i].hasChanged = false; + } + } + + public void SetAllFieldsToMaxValue() + { + for (int i = 0; i < fields.Length; i++) + { + fields[i].SetToMaxValue(); + } + } + + public static void Copy([NotNull] StatSheet src, [NotNull] StatSheet dest) + { + Array.Copy(src.fields, dest.fields, src.fields.Length); + dest.AllocateUnlockables(src.unlockables.Length); + Array.Copy(src.unlockables, dest.unlockables, src.unlockables.Length); + } + + public void DebugDisplay(string _prefix = "") + { + string text = _prefix + "\n"; + for (int i = 0; i < 5; i++) + { + text = text + fields[i].name + ": " + ((fields[i].dataType == StatDataType.ULong) ? ((double)fields[i].GetULongValue()) : fields[i].GetDoubleValue()); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.SurvivorMannequins/SurvivorMannequinDioramaController.cs b/ilspy_dump/ror2_csproj/RoR2.SurvivorMannequins/SurvivorMannequinDioramaController.cs new file mode 100644 index 0000000..24f7604 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.SurvivorMannequins/SurvivorMannequinDioramaController.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using HG; +using UnityEngine; + +namespace RoR2.SurvivorMannequins; + +public class SurvivorMannequinDioramaController : MonoBehaviour +{ + public bool showLocalPlayersFirst = true; + + [SerializeField] + private SurvivorMannequinSlotController[] mannequinSlots = Array.Empty(); + + private bool sortedNetworkUsersDirty = true; + + private List sortedNetworkUsers = new List(); + + private void OnEnable() + { + NetworkUser.onNetworkUserDiscovered += OnNetworkUserDiscovered; + NetworkUser.onNetworkUserLost += OnNetworkUserLost; + } + + private void OnDisable() + { + NetworkUser.onNetworkUserLost -= OnNetworkUserLost; + NetworkUser.onNetworkUserDiscovered -= OnNetworkUserDiscovered; + sortedNetworkUsers.Clear(); + UpdateMannequins(); + } + + private void Update() + { + if (sortedNetworkUsersDirty) + { + sortedNetworkUsersDirty = false; + UpdateSortedNetworkUsersList(); + } + UpdateMannequins(); + } + + private void UpdateSortedNetworkUsersList() + { + sortedNetworkUsers.Clear(); + if (showLocalPlayersFirst) + { + ListUtils.AddRange(sortedNetworkUsers, NetworkUser.readOnlyLocalPlayersList); + for (int i = 0; i < NetworkUser.readOnlyInstancesList.Count; i++) + { + ListUtils.AddIfUnique(sortedNetworkUsers, NetworkUser.readOnlyInstancesList[i]); + } + } + } + + private void OnNetworkUserLost(NetworkUser networkUser) + { + sortedNetworkUsersDirty = true; + } + + private void OnNetworkUserDiscovered(NetworkUser networkUser) + { + sortedNetworkUsersDirty = true; + } + + public void GetSlots(List dest) + { + if (dest == null) + { + throw new ArgumentNullException("dest"); + } + ListUtils.AddRange(dest, mannequinSlots); + } + + public void SetSlots(SurvivorMannequinSlotController[] newMannequinSlots) + { + if (newMannequinSlots == null) + { + throw new ArgumentNullException("newMannequinSlots"); + } + for (int i = 0; i < mannequinSlots.Length; i++) + { + SurvivorMannequinSlotController survivorMannequinSlotController = mannequinSlots[i]; + if ((bool)survivorMannequinSlotController && Array.IndexOf(newMannequinSlots, survivorMannequinSlotController) == -1) + { + survivorMannequinSlotController.networkUser = null; + } + } + ArrayUtils.CloneTo(newMannequinSlots, ref mannequinSlots); + UpdateMannequins(); + } + + private void UpdateMannequins() + { + AssignNetworkUsersToSlots(sortedNetworkUsers); + } + + private void AssignNetworkUsersToSlots(List networkUsers) + { + int i = 0; + for (int num = Math.Min(networkUsers.Count, mannequinSlots.Length); i < num; i++) + { + NetworkUser networkUser = networkUsers[i]; + SurvivorMannequinSlotController survivorMannequinSlotController = mannequinSlots[i]; + if (!survivorMannequinSlotController || (object)survivorMannequinSlotController.networkUser == networkUser) + { + continue; + } + for (int j = i + 1; j < mannequinSlots.Length; j++) + { + SurvivorMannequinSlotController survivorMannequinSlotController2 = mannequinSlots[j]; + if ((bool)survivorMannequinSlotController2) + { + SurvivorMannequinSlotController.Swap(survivorMannequinSlotController, survivorMannequinSlotController2); + break; + } + } + survivorMannequinSlotController.networkUser = networkUser; + } + for (int k = networkUsers.Count; k < mannequinSlots.Length; k++) + { + mannequinSlots[k].networkUser = null; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.SurvivorMannequins/SurvivorMannequinSlotController.cs b/ilspy_dump/ror2_csproj/RoR2.SurvivorMannequins/SurvivorMannequinSlotController.cs new file mode 100644 index 0000000..af478e0 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.SurvivorMannequins/SurvivorMannequinSlotController.cs @@ -0,0 +1,166 @@ +using HG; +using UnityEngine; + +namespace RoR2.SurvivorMannequins; + +public class SurvivorMannequinSlotController : MonoBehaviour +{ + public GameObject toggleableEffect; + + private NetworkUser _networkUser; + + private SurvivorDef _currentSurvivorDef; + + private Loadout currentLoadout; + + private bool loadoutDirty; + + private Transform mannequinInstanceTransform; + + private bool mannequinInstanceDirty; + + public NetworkUser networkUser + { + get + { + return _networkUser; + } + set + { + if ((object)_networkUser != value) + { + _networkUser = value; + mannequinInstanceDirty = true; + loadoutDirty = true; + } + } + } + + private SurvivorDef currentSurvivorDef + { + get + { + return _currentSurvivorDef; + } + set + { + if ((object)_currentSurvivorDef != value) + { + _currentSurvivorDef = value; + mannequinInstanceDirty = true; + } + } + } + + private void Awake() + { + currentLoadout = new Loadout(); + } + + private void OnEnable() + { + NetworkUser.onLoadoutChangedGlobal += OnLoadoutChangedGlobal; + } + + private void OnDisable() + { + NetworkUser.onLoadoutChangedGlobal -= OnLoadoutChangedGlobal; + } + + private void Update() + { + SurvivorDef survivorDef = null; + if ((bool)networkUser) + { + survivorDef = networkUser.GetSurvivorPreference(); + } + currentSurvivorDef = survivorDef; + if (mannequinInstanceDirty) + { + mannequinInstanceDirty = false; + RebuildMannequinInstance(); + } + if (loadoutDirty) + { + loadoutDirty = false; + if ((bool)networkUser) + { + networkUser.networkLoadout.CopyLoadout(currentLoadout); + } + ApplyLoadoutToMannequinInstance(); + } + if ((bool)toggleableEffect) + { + toggleableEffect.SetActive(networkUser); + } + } + + private void OnLoadoutChangedGlobal(NetworkUser networkUser) + { + if ((object)this.networkUser == networkUser) + { + loadoutDirty = true; + } + } + + private void ClearMannequinInstance() + { + if ((bool)mannequinInstanceTransform) + { + Object.Destroy(mannequinInstanceTransform.gameObject); + } + mannequinInstanceTransform = null; + } + + private void RebuildMannequinInstance() + { + ClearMannequinInstance(); + if ((bool)currentSurvivorDef && (bool)currentSurvivorDef.displayPrefab) + { + mannequinInstanceTransform = Object.Instantiate(currentSurvivorDef.displayPrefab, base.transform.position, base.transform.rotation, base.transform).transform; + CharacterSelectSurvivorPreviewDisplayController component = mannequinInstanceTransform.GetComponent(); + if ((bool)component) + { + component.networkUser = networkUser; + } + ApplyLoadoutToMannequinInstance(); + } + } + + private void ApplyLoadoutToMannequinInstance() + { + if (!mannequinInstanceTransform) + { + return; + } + BodyIndex bodyIndexFromSurvivorIndex = SurvivorCatalog.GetBodyIndexFromSurvivorIndex(currentSurvivorDef.survivorIndex); + int skinIndex = (int)currentLoadout.bodyLoadoutManager.GetSkinIndex(bodyIndexFromSurvivorIndex); + SkinDef safe = ArrayUtils.GetSafe(BodyCatalog.GetBodySkins(bodyIndexFromSurvivorIndex), skinIndex); + if ((bool)safe) + { + CharacterModel componentInChildren = mannequinInstanceTransform.GetComponentInChildren(); + if ((bool)componentInChildren) + { + safe.Apply(componentInChildren.gameObject); + } + } + } + + public static void Swap(SurvivorMannequinSlotController a, SurvivorMannequinSlotController b) + { + if ((bool)a.mannequinInstanceTransform) + { + a.mannequinInstanceTransform.SetParent(b.transform, worldPositionStays: false); + } + if ((bool)b.mannequinInstanceTransform) + { + b.mannequinInstanceTransform.SetParent(a.transform, worldPositionStays: false); + } + Util.Swap(ref a._networkUser, ref b._networkUser); + Util.Swap(ref a._currentSurvivorDef, ref b._currentSurvivorDef); + Util.Swap(ref a.currentLoadout, ref b.currentLoadout); + Util.Swap(ref a.loadoutDirty, ref b.loadoutDirty); + Util.Swap(ref a.mannequinInstanceDirty, ref b.mannequinInstanceDirty); + Util.Swap(ref a.mannequinInstanceTransform, ref b.mannequinInstanceTransform); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/CategoryDef.cs b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/CategoryDef.cs new file mode 100644 index 0000000..bb5b8e8 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/CategoryDef.cs @@ -0,0 +1,266 @@ +using System; +using System.Linq; +using JetBrains.Annotations; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.UI.LogBook; + +public class CategoryDef +{ + public class NavButtons + { + public string scroll = "SUBMENU_SCROLL"; + + public string back = "SUBMENU_BACK"; + + public string navigate = "LOGBOOK_ZOOMINOUT"; + + public string rotate = "LOGBOOK_ROTATE"; + } + + [NotNull] + public delegate Entry[] BuildEntriesDelegate([CanBeNull] UserProfile viewerProfile); + + [NotNull] + public string nameToken = string.Empty; + + private GameObject _iconPrefab; + + public Vector2 iconSize = Vector2.one; + + public bool fullWidth; + + public Action initializeElementGraphics = InitializeDefault; + + public NavButtons navButtons = new NavButtons(); + + [CanBeNull] + public ViewablesCatalog.Node viewableNode; + + public GameObject iconPrefab + { + get + { + return _iconPrefab; + } + [NotNull] + set + { + _iconPrefab = value; + iconSize = ((RectTransform)_iconPrefab.transform).sizeDelta; + } + } + + [NotNull] + public BuildEntriesDelegate buildEntries { private get; set; } + + public Entry[] BuildEntries([CanBeNull] UserProfile viewerProfile) + { + Entry[] array = buildEntries(viewerProfile); + for (int i = 0; i < array.Length; i++) + { + array[i].category = this; + } + return array; + } + + public static void InitializeDefault(GameObject gameObject, Entry entry, EntryStatus status, UserProfile userProfile) + { + Texture texture = null; + Texture texture2 = null; + Color color = Color.white; + switch (status) + { + case EntryStatus.Unimplemented: + texture = LegacyResourcesAPI.Load("Textures/MiscIcons/texWIPIcon"); + break; + case EntryStatus.Locked: + texture = LegacyResourcesAPI.Load("Textures/MiscIcons/texUnlockIcon"); + color = Color.gray; + break; + case EntryStatus.Unencountered: + texture = entry.iconTexture; + color = Color.black; + break; + case EntryStatus.Available: + texture = entry.iconTexture; + texture2 = entry.bgTexture; + color = Color.white; + break; + case EntryStatus.New: + texture = entry.iconTexture; + texture2 = entry.bgTexture; + color = new Color(1f, 0.8f, 0.5f, 1f); + break; + default: + throw new ArgumentOutOfRangeException("status", status, null); + } + RawImage rawImage = null; + RawImage rawImage2 = null; + ChildLocator component = gameObject.GetComponent(); + if ((bool)component) + { + rawImage = component.FindChild("Icon").GetComponent(); + rawImage2 = component.FindChild("BG").GetComponent(); + } + else + { + rawImage = gameObject.GetComponentInChildren(); + } + rawImage.texture = texture; + rawImage.color = color; + if ((bool)rawImage2) + { + if (texture2 != null) + { + rawImage2.texture = texture2; + } + else + { + rawImage2.enabled = false; + } + } + TextMeshProUGUI componentInChildren = gameObject.GetComponentInChildren(); + if ((bool)componentInChildren) + { + if (status >= EntryStatus.Available) + { + componentInChildren.text = entry.GetDisplayName(userProfile); + } + else + { + componentInChildren.text = Language.GetString("UNIDENTIFIED"); + } + } + } + + public static void InitializeChallenge(GameObject gameObject, Entry entry, EntryStatus status, UserProfile userProfile) + { + TextMeshProUGUI textMeshProUGUI = null; + TextMeshProUGUI textMeshProUGUI2 = null; + RawImage rawImage = null; + AchievementDef achievementDef = (AchievementDef)entry.extraData; + float achievementProgress = AchievementManager.GetUserAchievementManager(LocalUserManager.readOnlyLocalUsersList.FirstOrDefault((LocalUser v) => v.userProfile == userProfile)).GetAchievementProgress(achievementDef); + HGButton component = gameObject.GetComponent(); + if ((bool)component) + { + component.disablePointerClick = true; + component.disableGamepadClick = true; + } + ChildLocator component2 = gameObject.GetComponent(); + if ((bool)component2) + { + textMeshProUGUI = component2.FindChild("DescriptionLabel").GetComponent(); + textMeshProUGUI2 = component2.FindChild("NameLabel").GetComponent(); + rawImage = component2.FindChild("RewardImage").GetComponent(); + textMeshProUGUI2.text = Language.GetString(achievementDef.nameToken); + textMeshProUGUI.text = Language.GetString(achievementDef.descriptionToken); + } + Texture texture = null; + Color color = Color.white; + switch (status) + { + case EntryStatus.Unimplemented: + texture = LegacyResourcesAPI.Load("Textures/MiscIcons/texWIPIcon"); + break; + case EntryStatus.Locked: + texture = LegacyResourcesAPI.Load("Textures/MiscIcons/texUnlockIcon"); + color = Color.black; + textMeshProUGUI2.text = Language.GetString("UNIDENTIFIED"); + textMeshProUGUI.text = Language.GetString("UNIDENTIFIED_DESCRIPTION"); + component2.FindChild("CantBeAchieved").gameObject.SetActive(value: true); + break; + case EntryStatus.Unencountered: + texture = LegacyResourcesAPI.Load("Textures/MiscIcons/texUnlockIcon"); + color = Color.gray; + component2.FindChild("ProgressTowardsUnlocking").GetComponent().fillAmount = achievementProgress; + break; + case EntryStatus.Available: + texture = entry.iconTexture; + color = Color.white; + component2.FindChild("HasBeenUnlocked").gameObject.SetActive(value: true); + break; + case EntryStatus.New: + texture = entry.iconTexture; + color = new Color(1f, 0.8f, 0.5f, 1f); + component2.FindChild("HasBeenUnlocked").gameObject.SetActive(value: true); + break; + case EntryStatus.None: + component2.FindChild("RewardImageContainer").gameObject.SetActive(value: true); + textMeshProUGUI2.text = ""; + textMeshProUGUI.text = ""; + break; + default: + throw new ArgumentOutOfRangeException("status", status, null); + } + if (texture != null) + { + rawImage.texture = texture; + rawImage.color = color; + } + else + { + rawImage.enabled = false; + } + } + + public static void InitializeMorgue(GameObject gameObject, Entry entry, EntryStatus status, UserProfile userProfile) + { + RunReport runReport = entry.extraData as RunReport; + GameEndingDef gameEnding = runReport.gameEnding; + ChildLocator component = gameObject.GetComponent(); + if ((bool)component) + { + TextMeshProUGUI component2 = component.FindChild("DescriptionLabel").GetComponent(); + TextMeshProUGUI component3 = component.FindChild("NameLabel").GetComponent(); + RawImage component4 = component.FindChild("IconImage").GetComponent(); + Image component5 = component.FindChild("BackgroundImage").GetComponent(); + Texture iconTexture = entry.iconTexture; + component3.text = entry.GetDisplayName(userProfile); + component2.text = Language.GetString(runReport.gameEnding?.endingTextToken ?? string.Empty); + component2.color = gameEnding?.foregroundColor ?? Color.white; + component5.color = gameEnding?.backgroundColor ?? Color.black; + if (iconTexture != null) + { + component4.texture = iconTexture; + } + else + { + component4.enabled = false; + } + } + } + + public static void InitializeStats(GameObject gameObject, Entry entry, EntryStatus status, UserProfile userProfile) + { + UserProfile userProfile2 = entry.extraData as UserProfile; + ChildLocator component = gameObject.GetComponent(); + if ((bool)component) + { + TextMeshProUGUI component2 = component.FindChild("NameLabel").GetComponent(); + TextMeshProUGUI component3 = component.FindChild("TimeLabel").GetComponent(); + TextMeshProUGUI component4 = component.FindChild("CompletionLabel").GetComponent(); + RawImage component5 = component.FindChild("IconImage").GetComponent(); + component.FindChild("BackgroundImage").GetComponent(); + Texture iconTexture = entry.iconTexture; + IntFraction value = new GameCompletionStatsHelper().GetTotalCompletion(userProfile2); + float num = (float)value; + string text = $"{num:0%}"; + TimeSpan timeSpan = TimeSpan.FromSeconds(userProfile2.totalLoginSeconds); + string text2 = $"{(uint)timeSpan.TotalHours}:{(uint)timeSpan.Minutes:D2}"; + component2.text = entry.GetDisplayName(userProfile2); + component3.text = text2; + component4.text = text; + if (iconTexture != null) + { + component5.texture = iconTexture; + } + else + { + component5.enabled = false; + } + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/Entry.cs b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/Entry.cs new file mode 100644 index 0000000..b598df4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/Entry.cs @@ -0,0 +1,109 @@ +using System; +using JetBrains.Annotations; +using UnityEngine; + +namespace RoR2.UI.LogBook; + +public class Entry +{ + public delegate EntryStatus GetStatusDelegate(in Entry entry, [NotNull] UserProfile viewerProfile); + + public delegate TooltipContent GetTooltipContentDelegate(in Entry entry, UserProfile viewerProfile, EntryStatus entryStatus); + + [NotNull] + public delegate string GetDisplayNameDelegate(in Entry entry, [NotNull] UserProfile viewerProfile); + + public delegate bool IsWIPDelegate(in Entry entry); + + public string nameToken; + + public CategoryDef category; + + public Texture iconTexture; + + public Texture bgTexture; + + public Color color; + + public GameObject modelPrefab; + + public object extraData; + + public Action pageBuilderMethod; + + [CanBeNull] + public ViewablesCatalog.Node viewableNode; + + [NotNull] + public GetStatusDelegate getStatusImplementation { private get; set; } = GetStatusDefault; + + + public GetTooltipContentDelegate getTooltipContentImplementation { private get; set; } = GetTooltipContentDefault; + + + [NotNull] + public GetDisplayNameDelegate getDisplayNameImplementation { private get; set; } = GetDisplayNameDefault; + + + [NotNull] + public GetDisplayNameDelegate getCategoryDisplayNameImplementation { private get; set; } = GetCategoryDisplayNameDefault; + + + [NotNull] + public IsWIPDelegate isWIPImplementation { private get; set; } = IsWIPReturnFalse; + + + public bool isWip => isWIPImplementation(in this); + + public static EntryStatus GetStatusDefault(in Entry entry, [NotNull] UserProfile viewerProfile) + { + return EntryStatus.Unimplemented; + } + + public EntryStatus GetStatus([NotNull] UserProfile viewerProfile) + { + return getStatusImplementation(in this, viewerProfile); + } + + public static TooltipContent GetTooltipContentDefault(in Entry entry, [NotNull] UserProfile viewerProfile, EntryStatus entryStatus) + { + TooltipContent result = default(TooltipContent); + result.overrideTitleText = entry.GetDisplayName(viewerProfile); + result.overrideBodyText = entry.GetCategoryDisplayName(viewerProfile); + return result; + } + + public TooltipContent GetTooltipContent([NotNull] UserProfile viewerProfile, EntryStatus entryStatus) + { + return getTooltipContentImplementation(in this, viewerProfile, entryStatus); + } + + [NotNull] + public static string GetDisplayNameDefault(in Entry entry, [NotNull] UserProfile viewerProfile) + { + return Language.GetString(entry.nameToken ?? string.Empty); + } + + [NotNull] + public string GetDisplayName([NotNull] UserProfile viewerProfile) + { + return getDisplayNameImplementation(in this, viewerProfile); + } + + [NotNull] + public static string GetCategoryDisplayNameDefault(in Entry entry, [NotNull] UserProfile viewerProfile) + { + return Language.GetString(entry.category?.nameToken ?? string.Empty); + } + + [NotNull] + public string GetCategoryDisplayName([NotNull] UserProfile viewerProfile) + { + return getCategoryDisplayNameImplementation(in this, viewerProfile); + } + + private static bool IsWIPReturnFalse(in Entry entry) + { + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/EntryStatus.cs b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/EntryStatus.cs new file mode 100644 index 0000000..8ba2f46 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/EntryStatus.cs @@ -0,0 +1,11 @@ +namespace RoR2.UI.LogBook; + +public enum EntryStatus +{ + None, + Unimplemented, + Locked, + Unencountered, + Available, + New +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/LogBookController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/LogBookController.cs new file mode 100644 index 0000000..2b50ee4 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/LogBookController.cs @@ -0,0 +1,1657 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using EntityStates; +using HG; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Stats; +using TMPro; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; + +namespace RoR2.UI.LogBook; + +public class LogBookController : MonoBehaviour +{ + private class NavigationPageInfo + { + public CategoryDef categoryDef; + + public Entry[] entries; + + public int index; + + public int indexInCategory; + } + + private class LogBookState : EntityState + { + protected LogBookController logBookController; + + protected float unscaledAge; + + public override void OnEnter() + { + base.OnEnter(); + logBookController = GetComponent(); + } + + public override void Update() + { + base.Update(); + unscaledAge += Time.unscaledDeltaTime; + } + } + + private class FadeState : LogBookState + { + private CanvasGroup canvasGroup; + + public float duration = 0.5f; + + public float endValue; + + public override void OnEnter() + { + base.OnEnter(); + canvasGroup = GetComponent(); + if ((bool)canvasGroup) + { + canvasGroup.alpha = 0f; + } + } + + public override void OnExit() + { + if ((bool)canvasGroup) + { + canvasGroup.alpha = endValue; + } + base.OnExit(); + } + + public override void Update() + { + if ((bool)canvasGroup) + { + canvasGroup.alpha = unscaledAge / duration; + if (canvasGroup.alpha >= 1f) + { + outer.SetNextState(new Idle()); + } + } + base.Update(); + } + } + + private class ChangeEntriesPageState : LogBookState + { + private int oldPageIndex; + + public NavigationPageInfo newNavigationPageInfo; + + public float duration = 0.1f; + + public Vector2 moveDirection; + + private GameObject oldPage; + + private GameObject newPage; + + private Vector2 oldPageTargetPosition; + + private Vector2 newPageTargetPosition; + + private Vector2 containerSize = Vector2.zero; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)logBookController) + { + oldPageIndex = logBookController.currentPageIndex; + oldPage = logBookController.currentEntriesPageObject; + newPage = logBookController.BuildEntriesPage(newNavigationPageInfo); + containerSize = logBookController.entryPageContainer.rect.size; + } + SetPagePositions(0f); + } + + public override void OnExit() + { + base.OnExit(); + EntityState.Destroy(oldPage); + if ((bool)logBookController) + { + logBookController.currentEntriesPageObject = newPage; + logBookController.currentPageIndex = newNavigationPageInfo.indexInCategory; + } + } + + private void SetPagePositions(float t) + { + Vector2 vector = new Vector2(containerSize.x * (0f - moveDirection.x), containerSize.y * moveDirection.y); + Vector2 vector2 = vector * t; + if ((bool)oldPage) + { + oldPage.transform.localPosition = vector2; + } + if ((bool)newPage) + { + newPage.transform.localPosition = vector2 - vector; + } + } + + public override void Update() + { + base.Update(); + float num = Mathf.Clamp01(unscaledAge / duration); + SetPagePositions(num); + if (num == 1f) + { + outer.SetNextState(new Idle()); + } + } + } + + private class ChangeCategoryState : LogBookState + { + private int oldCategoryIndex; + + public int newCategoryIndex; + + public bool goToLastPage; + + public float duration = 0.1f; + + private GameObject oldPage; + + private GameObject newPage; + + private Vector2 oldPageTargetPosition; + + private Vector2 newPageTargetPosition; + + private Vector2 moveDirection; + + private Vector2 containerSize = Vector2.zero; + + private NavigationPageInfo[] newNavigationPages; + + private int destinationPageIndex; + + private NavigationPageInfo newNavigationPageInfo; + + private int frame; + + public override void OnEnter() + { + base.OnEnter(); + if ((bool)logBookController) + { + oldCategoryIndex = logBookController.currentCategoryIndex; + oldPage = logBookController.currentEntriesPageObject; + newNavigationPages = logBookController.GetCategoryPages(newCategoryIndex); + destinationPageIndex = newNavigationPages[0].index; + if (goToLastPage) + { + destinationPageIndex = newNavigationPages[newNavigationPages.Length - 1].index; + Debug.LogFormat("goToLastPage=true destinationPageIndex={0}", destinationPageIndex); + } + newNavigationPageInfo = logBookController.allNavigationPages[destinationPageIndex]; + newPage = logBookController.BuildEntriesPage(newNavigationPageInfo); + containerSize = logBookController.entryPageContainer.rect.size; + moveDirection = new Vector2(Mathf.Sign(newCategoryIndex - oldCategoryIndex), 0f); + } + SetPagePositions(0f); + } + + public override void OnExit() + { + EntityState.Destroy(oldPage); + if ((bool)logBookController) + { + logBookController.currentEntriesPageObject = newPage; + logBookController.currentPageIndex = newNavigationPageInfo.indexInCategory; + logBookController.desiredPageIndex = newNavigationPageInfo.indexInCategory; + logBookController.currentCategoryIndex = newCategoryIndex; + logBookController.availableNavigationPages = newNavigationPages; + logBookController.currentCategoryLabel.token = categories[newCategoryIndex].nameToken; + logBookController.categoryHightlightRect.SetParent(logBookController.navigationCategoryButtonAllocator.elements[newCategoryIndex].transform, worldPositionStays: false); + logBookController.categoryHightlightRect.gameObject.SetActive(value: false); + logBookController.categoryHightlightRect.gameObject.SetActive(value: true); + if (logBookController.moveNavigationPageIndicatorContainerToCategoryButton) + { + logBookController.navigationPageIndicatorContainer.SetParent(logBookController.navigationCategoryButtonAllocator.elements[newCategoryIndex].transform, worldPositionStays: false); + } + } + base.OnExit(); + } + + private void SetPagePositions(float t) + { + Vector2 vector = new Vector2(containerSize.x * (0f - moveDirection.x), containerSize.y * moveDirection.y); + Vector2 vector2 = vector * t; + if ((bool)oldPage) + { + oldPage.transform.localPosition = vector2; + } + if ((bool)newPage) + { + newPage.transform.localPosition = vector2 - vector; + if (frame == 4) + { + newPage.GetComponent().enabled = false; + } + } + } + + public override void Update() + { + base.Update(); + frame++; + float num = Mathf.Clamp01(unscaledAge / duration); + SetPagePositions(num); + if (num == 1f) + { + outer.SetNextState(new Idle()); + } + } + } + + private class EnterLogViewState : LogBookState + { + public Texture iconTexture; + + public RectTransform startRectTransform; + + public RectTransform endRectTransform; + + public Entry entry; + + private GameObject flyingIcon; + + private RectTransform flyingIconTransform; + + private RawImage flyingIconImage; + + private float duration = 0.75f; + + private Rect startRect; + + private Rect midRect; + + private Rect endRect; + + private bool submittedViewEntry; + + public override void OnEnter() + { + base.OnEnter(); + flyingIcon = new GameObject("FlyingIcon", typeof(RectTransform), typeof(CanvasRenderer), typeof(RawImage)); + flyingIconTransform = (RectTransform)flyingIcon.transform; + flyingIconTransform.SetParent(logBookController.transform, worldPositionStays: false); + flyingIconTransform.localScale = Vector3.one; + flyingIconImage = flyingIconTransform.GetComponent(); + flyingIconImage.texture = iconTexture; + Vector3[] array = new Vector3[4]; + startRectTransform.GetWorldCorners(array); + startRect = GetRectRelativeToParent(array); + midRect = new Rect(((RectTransform)logBookController.transform).rect.center, startRect.size); + endRectTransform.GetWorldCorners(array); + endRect = GetRectRelativeToParent(array); + SetIconRect(startRect); + } + + private void SetIconRect(Rect rect) + { + flyingIconTransform.position = rect.position; + flyingIconTransform.offsetMin = rect.min; + flyingIconTransform.offsetMax = rect.max; + } + + private Rect GetRectRelativeToParent(Vector3[] corners) + { + for (int i = 0; i < 4; i++) + { + corners[i] = logBookController.transform.InverseTransformPoint(corners[i]); + } + Rect result = default(Rect); + result.xMin = corners[0].x; + result.xMax = corners[2].x; + result.yMin = corners[0].y; + result.yMax = corners[2].y; + return result; + } + + private static Rect RectFromWorldCorners(Vector3[] corners) + { + Rect result = default(Rect); + result.xMin = corners[0].x; + result.xMax = corners[2].x; + result.yMin = corners[0].y; + result.yMax = corners[2].y; + return result; + } + + private static Rect LerpRect(Rect a, Rect b, float t) + { + Rect result = default(Rect); + result.min = Vector2.LerpUnclamped(a.min, b.min, t); + result.max = Vector2.LerpUnclamped(a.max, b.max, t); + return result; + } + + public override void OnExit() + { + EntityState.Destroy(flyingIcon); + base.OnExit(); + } + + public override void Update() + { + base.Update(); + float num = Mathf.Min(unscaledAge / duration, 1f); + if (num < 0.1f) + { + Util.Remap(num, 0f, 0.1f, 0f, 1f); + SetIconRect(startRect); + } + if (num < 0.2f) + { + float t = Util.Remap(num, 0.1f, 0.2f, 0f, 1f); + SetIconRect(LerpRect(startRect, midRect, t)); + } + else if (num < 0.4f) + { + Util.Remap(num, 0.2f, 0.4f, 0f, 1f); + SetIconRect(midRect); + } + else if (num < 0.6f) + { + float t2 = Util.Remap(num, 0.4f, 0.6f, 0f, 1f); + SetIconRect(LerpRect(midRect, endRect, t2)); + } + else if (num < 1f) + { + float num2 = Util.Remap(num, 0.6f, 1f, 0f, 1f); + flyingIconImage.color = new Color(1f, 1f, 1f, 1f - num2); + SetIconRect(endRect); + if (!submittedViewEntry) + { + submittedViewEntry = true; + logBookController.ViewEntry(entry); + } + } + else + { + outer.SetNextState(new Idle()); + } + } + } + + [Header("Navigation")] + public GameObject navigationPanel; + + public RectTransform categoryContainer; + + public GameObject categorySpaceFiller; + + public int categorySpaceFillerCount; + + public Color spaceFillerColor; + + private UIElementAllocator navigationCategoryButtonAllocator; + + public RectTransform entryPageContainer; + + public GameObject entryPagePrefab; + + public RectTransform navigationPageIndicatorContainer; + + public GameObject navigationPageIndicatorPrefab; + + public bool moveNavigationPageIndicatorContainerToCategoryButton; + + private UIElementAllocator navigationPageIndicatorAllocator; + + public MPButton previousPageButton; + + public MPButton nextPageButton; + + public LanguageTextMeshController currentCategoryLabel; + + private RectTransform categoryHightlightRect; + + [Header("PageViewer")] + public UnityEvent OnViewEntry; + + public GameObject pageViewerPanel; + + public MPButton pageViewerBackButton; + + [Header("Misc")] + public GameObject categoryButtonPrefab; + + public GameObject headerHighlightPrefab; + + public LanguageTextMeshController hoverLanguageTextMeshController; + + public string hoverDescriptionFormatString; + + private EntityStateMachine stateMachine; + + private UILayerKey uiLayerKey; + + public static CategoryDef[] categories; + + public static ResourceAvailability availability; + + private static bool IsInitialized; + + public static bool IsStaticDataReady; + + private NavigationPageInfo[] _availableNavigationPages = Array.Empty(); + + private GameObject currentEntriesPageObject; + + private int currentCategoryIndex; + + private int desiredCategoryIndex; + + private int currentPageIndex; + + private int desiredPageIndex; + + private bool goToEndOfNextCategory; + + private NavigationPageInfo[] allNavigationPages; + + private NavigationPageInfo[][] navigationPagesByCategory; + + private static List lastBuiltEntitlements; + + private NavigationPageInfo[] availableNavigationPages + { + get + { + return _availableNavigationPages; + } + set + { + int num = _availableNavigationPages.Length; + _availableNavigationPages = value; + if (num != availableNavigationPages.Length) + { + navigationPageIndicatorAllocator.AllocateElements(availableNavigationPages.Length); + } + } + } + + public static event Action OnViewablesRegistered; + + private void Awake() + { + EntitlementManager.UpdateLocalUsersEntitlements(); + navigationCategoryButtonAllocator = new UIElementAllocator(categoryContainer, categoryButtonPrefab); + navigationPageIndicatorAllocator = new UIElementAllocator(navigationPageIndicatorContainer, navigationPageIndicatorPrefab); + navigationPageIndicatorAllocator.onCreateElement = delegate(int index, MPButton button) + { + button.onClick.AddListener(delegate + { + desiredPageIndex = index; + }); + }; + previousPageButton.onClick.AddListener(OnLeftButton); + nextPageButton.onClick.AddListener(OnRightButton); + pageViewerBackButton.onClick.AddListener(ReturnToNavigation); + stateMachine = base.gameObject.AddComponent(); + uiLayerKey = base.gameObject.GetComponent(); + stateMachine.initialStateType = default(SerializableEntityStateType); + stateMachine.AllowStartWithoutNetworker = true; + stateMachine.ShouldStateTransitionOnUpdate = true; + categoryHightlightRect = (RectTransform)UnityEngine.Object.Instantiate(headerHighlightPrefab, base.transform.parent).transform; + categoryHightlightRect.gameObject.SetActive(value: false); + } + + private void Start() + { + GeneratePages(LocalUserManager.GetFirstLocalUser()?.userProfile); + BuildCategoriesButtons(); + stateMachine.SetNextState(new ChangeCategoryState + { + newCategoryIndex = 0 + }); + } + + private void BuildCategoriesButtons() + { + navigationCategoryButtonAllocator.AllocateElements(categories.Length); + ReadOnlyCollection elements = navigationCategoryButtonAllocator.elements; + for (int i = 0; i < categories.Length; i++) + { + int categoryIndex = i; + MPButton mPButton = elements[i]; + CategoryDef categoryDef = categories[i]; + mPButton.GetComponentInChildren().text = Language.GetString(categoryDef.nameToken); + mPButton.onClick.RemoveAllListeners(); + mPButton.onClick.AddListener(delegate + { + OnCategoryClicked(categoryIndex); + }); + mPButton.requiredTopLayer = uiLayerKey; + ViewableTag viewableTag = mPButton.gameObject.GetComponent(); + if (!viewableTag) + { + viewableTag = mPButton.gameObject.AddComponent(); + } + viewableTag.viewableName = categoryDef.viewableNode.fullName; + } + if ((bool)categorySpaceFiller) + { + for (int j = 0; j < categorySpaceFillerCount; j++) + { + UnityEngine.Object.Instantiate(categorySpaceFiller, categoryContainer).gameObject.SetActive(value: true); + } + } + } + + public static IEnumerator Init() + { + if (LocalUserManager.isAnyUserSignedIn) + { + BuildStaticData(); + } + yield return null; + LocalUserManager.onUserSignIn += OnUserSignIn; + BaseUserEntitlementTracker.OnUserEntitlementsUpdated = (Action)Delegate.Combine(BaseUserEntitlementTracker.OnUserEntitlementsUpdated, new Action(BuildStaticData)); + IsInitialized = true; + } + + private static void OnUserSignIn(LocalUser obj) + { + BuildStaticData(); + } + + private static EntryStatus GetPickupStatus(in Entry entry, UserProfile viewerProfile) + { + UnlockableDef unlockableDef = null; + PickupIndex pickupIndex = (PickupIndex)entry.extraData; + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + ItemIndex itemIndex = pickupDef?.itemIndex ?? ItemIndex.None; + EquipmentIndex equipmentIndex = pickupDef?.equipmentIndex ?? EquipmentIndex.None; + if (itemIndex != ItemIndex.None) + { + unlockableDef = ItemCatalog.GetItemDef(itemIndex).unlockableDef; + } + else + { + if (equipmentIndex == EquipmentIndex.None) + { + return EntryStatus.Unimplemented; + } + unlockableDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex).unlockableDef; + } + if (!viewerProfile.HasUnlockable(unlockableDef)) + { + return EntryStatus.Locked; + } + if (!viewerProfile.HasDiscoveredPickup(pickupIndex)) + { + return EntryStatus.Unencountered; + } + return EntryStatus.Available; + } + + private static TooltipContent GetPickupTooltipContent(in Entry entry, UserProfile userProfile, EntryStatus status) + { + UnlockableDef unlockableDef = PickupCatalog.GetPickupDef((PickupIndex)entry.extraData).unlockableDef; + TooltipContent result = default(TooltipContent); + if (status >= EntryStatus.Available) + { + result.overrideTitleText = entry.GetDisplayName(userProfile); + result.titleColor = entry.color; + if (unlockableDef != null) + { + result.overrideBodyText = unlockableDef.getUnlockedString(); + } + result.bodyToken = ""; + result.bodyColor = ColorCatalog.GetColor(ColorCatalog.ColorIndex.Unlockable); + } + else + { + result.titleToken = "UNIDENTIFIED"; + result.titleColor = Color.gray; + result.bodyToken = ""; + switch (status) + { + case EntryStatus.Unimplemented: + result.titleToken = "TOOLTIP_WIP_CONTENT_NAME"; + result.bodyToken = "TOOLTIP_WIP_CONTENT_DESCRIPTION"; + break; + case EntryStatus.Unencountered: + result.overrideBodyText = Language.GetString("LOGBOOK_UNLOCK_ITEM_LOG"); + break; + case EntryStatus.Locked: + result.overrideBodyText = unlockableDef.getHowToUnlockString(); + break; + } + result.bodyColor = Color.white; + } + return result; + } + + private static TooltipContent GetMonsterTooltipContent(in Entry entry, UserProfile userProfile, EntryStatus status) + { + TooltipContent result = default(TooltipContent); + result.titleColor = entry.color; + if (status >= EntryStatus.Available) + { + result.overrideTitleText = entry.GetDisplayName(userProfile); + result.titleColor = entry.color; + result.bodyToken = ""; + } + else + { + result.titleToken = "UNIDENTIFIED"; + result.titleColor = Color.gray; + result.bodyToken = "LOGBOOK_UNLOCK_ITEM_MONSTER"; + } + return result; + } + + private static TooltipContent GetStageTooltipContent(in Entry entry, UserProfile userProfile, EntryStatus status) + { + TooltipContent result = default(TooltipContent); + result.titleColor = entry.color; + if (status >= EntryStatus.Available) + { + result.overrideTitleText = entry.GetDisplayName(userProfile); + result.titleColor = entry.color; + result.bodyToken = ""; + } + else + { + result.titleToken = "UNIDENTIFIED"; + result.titleColor = Color.gray; + result.bodyToken = "LOGBOOK_UNLOCK_ITEM_STAGE"; + } + return result; + } + + private static TooltipContent GetSurvivorTooltipContent(in Entry entry, UserProfile userProfile, EntryStatus status) + { + TooltipContent result = default(TooltipContent); + UnlockableDef unlockableDef = SurvivorCatalog.FindSurvivorDefFromBody(((CharacterBody)entry.extraData).gameObject).unlockableDef; + if (status >= EntryStatus.Available) + { + result.overrideTitleText = entry.GetDisplayName(userProfile); + result.titleColor = entry.color; + result.bodyToken = ""; + } + else + { + result.titleToken = "UNIDENTIFIED"; + result.bodyToken = ""; + result.titleColor = Color.gray; + switch (status) + { + case EntryStatus.Unencountered: + result.overrideBodyText = Language.GetString("LOGBOOK_UNLOCK_ITEM_SURVIVOR"); + break; + case EntryStatus.Locked: + result.overrideBodyText = unlockableDef.getHowToUnlockString(); + break; + } + } + return result; + } + + private static TooltipContent GetAchievementTooltipContent(in Entry entry, UserProfile userProfile, EntryStatus status) + { + TooltipContent result = default(TooltipContent); + UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(((AchievementDef)entry.extraData).unlockableRewardIdentifier); + result.titleColor = entry.color; + result.bodyToken = ""; + if (unlockableDef == null) + { + result.overrideTitleText = entry.GetDisplayName(userProfile); + result.titleColor = Color.gray; + result.overrideBodyText = "ACHIEVEMENT HAS NO UNLOCKABLE DEFINED"; + result.bodyColor = Color.white; + return result; + } + if (status >= EntryStatus.Available) + { + result.titleToken = entry.GetDisplayName(userProfile); + result.titleColor = entry.color; + result.overrideBodyText = unlockableDef.getUnlockedString(); + } + else + { + result.titleToken = "UNIDENTIFIED"; + result.titleColor = Color.gray; + if (status == EntryStatus.Locked) + { + result.overrideBodyText = Language.GetString("UNIDENTIFIED_DESCRIPTION"); + } + else + { + result.overrideBodyText = unlockableDef.getHowToUnlockString(); + } + } + return result; + } + + private static TooltipContent GetWIPTooltipContent(in Entry entry, UserProfile userProfile, EntryStatus status) + { + TooltipContent result = default(TooltipContent); + result.titleColor = ColorCatalog.GetColor(ColorCatalog.ColorIndex.WIP); + result.titleToken = "TOOLTIP_WIP_CONTENT_NAME"; + result.bodyToken = "TOOLTIP_WIP_CONTENT_DESCRIPTION"; + return result; + } + + private static EntryStatus GetAlwaysAvailable(UserProfile userProfile, Entry entry) + { + return EntryStatus.Available; + } + + private static EntryStatus GetUnimplemented(in Entry entry, UserProfile viewerProfile) + { + return EntryStatus.Unimplemented; + } + + private static EntryStatus GetStageStatus(in Entry entry, UserProfile viewerProfile) + { + UnlockableDef unlockableLogFromBaseSceneName = SceneCatalog.GetUnlockableLogFromBaseSceneName((entry.extraData as SceneDef).baseSceneName); + if (unlockableLogFromBaseSceneName != null && viewerProfile.HasUnlockable(unlockableLogFromBaseSceneName)) + { + return EntryStatus.Available; + } + return EntryStatus.Unencountered; + } + + private static EntryStatus GetMonsterStatus(in Entry entry, UserProfile viewerProfile) + { + CharacterBody characterBody = (CharacterBody)entry.extraData; + UnlockableDef unlockableDef = characterBody.GetComponent()?.logUnlockableDef; + if (!unlockableDef) + { + return EntryStatus.None; + } + if (viewerProfile.HasUnlockable(unlockableDef)) + { + return EntryStatus.Available; + } + if (viewerProfile.statSheet.GetStatValueULong(PerBodyStatDef.killsAgainst, characterBody.gameObject.name) != 0) + { + return EntryStatus.Unencountered; + } + return EntryStatus.Locked; + } + + private static EntryStatus GetSurvivorStatus(in Entry entry, UserProfile viewerProfile) + { + CharacterBody characterBody = (CharacterBody)entry.extraData; + SurvivorDef survivorDef = SurvivorCatalog.FindSurvivorDefFromBody(characterBody.gameObject); + if (!viewerProfile.HasUnlockable(survivorDef.unlockableDef)) + { + return EntryStatus.Locked; + } + if (viewerProfile.statSheet.GetStatValueULong(PerBodyStatDef.totalWins, characterBody.gameObject.name) == 0L) + { + return EntryStatus.Unencountered; + } + return EntryStatus.Available; + } + + private static EntryStatus GetAchievementStatus(in Entry entry, UserProfile viewerProfile) + { + string identifier = ((AchievementDef)entry.extraData).identifier; + bool flag = viewerProfile.HasAchievement(identifier); + if (!viewerProfile.CanSeeAchievement(identifier)) + { + return EntryStatus.Locked; + } + if (!flag) + { + return EntryStatus.Unencountered; + } + return EntryStatus.Available; + } + + private static void BuildStaticData() + { + RoR2Application.instance.StartCoroutine(WaitForBuildingStaticData()); + } + + static LogBookController() + { + categories = Array.Empty(); + availability = default(ResourceAvailability); + IsInitialized = false; + IsStaticDataReady = false; + lastBuiltEntitlements = null; + } + + private NavigationPageInfo[] GetCategoryPages(int categoryIndex) + { + if (navigationPagesByCategory.GetLength(0) <= categoryIndex) + { + return new NavigationPageInfo[0]; + } + return navigationPagesByCategory[categoryIndex]; + } + + public void OnLeftButton() + { + desiredPageIndex--; + } + + public void OnRightButton() + { + desiredPageIndex++; + } + + private void OnCategoryClicked(int categoryIndex) + { + desiredCategoryIndex = categoryIndex; + goToEndOfNextCategory = false; + } + + public void OnCategoryLeftButton() + { + desiredCategoryIndex--; + goToEndOfNextCategory = false; + } + + public void OnCategoryRightButton() + { + desiredCategoryIndex++; + goToEndOfNextCategory = false; + } + + private void GeneratePages(UserProfile viewerProfile) + { + if (!IsInitialized) + { + Init(); + } + navigationPagesByCategory = new NavigationPageInfo[categories.Length][]; + IEnumerable enumerable = Array.Empty(); + int num = 0; + for (int i = 0; i < categories.Length; i++) + { + CategoryDef categoryDef = categories[i]; + Entry[] array = categoryDef.BuildEntries(viewerProfile); + bool fullWidth = categoryDef.fullWidth; + Vector2 size = entryPageContainer.rect.size; + if (fullWidth) + { + categoryDef.iconSize.x = size.x; + } + int num2 = Mathf.FloorToInt(Mathf.Max(size.x / categoryDef.iconSize.x, 1f)); + int num3 = Mathf.FloorToInt(Mathf.Max(size.y / categoryDef.iconSize.y, 1f)); + int num4 = num2 * num3; + int num5 = Mathf.CeilToInt((float)array.Length / (float)num4); + if (num5 <= 0) + { + num5 = 1; + } + NavigationPageInfo[] array2 = new NavigationPageInfo[num5]; + for (int j = 0; j < num5; j++) + { + int num6 = j * num4; + int num7 = array.Length - num6; + int num8 = num4; + if (num8 > num7) + { + num8 = num7; + } + Entry[] array3 = new Entry[num4]; + Array.Copy(array, num6, array3, 0, num8); + NavigationPageInfo navigationPageInfo = new NavigationPageInfo(); + navigationPageInfo.categoryDef = categoryDef; + navigationPageInfo.entries = array3; + navigationPageInfo.index = num++; + navigationPageInfo.indexInCategory = j; + array2[j] = navigationPageInfo; + } + navigationPagesByCategory[i] = array2; + enumerable = enumerable.Concat(array2); + } + allNavigationPages = enumerable.ToArray(); + } + + private void Update() + { + if (desiredPageIndex > availableNavigationPages.Length - 1) + { + desiredPageIndex = availableNavigationPages.Length - 1; + desiredCategoryIndex++; + goToEndOfNextCategory = false; + } + if (desiredPageIndex < 0) + { + desiredCategoryIndex--; + desiredPageIndex = 0; + goToEndOfNextCategory = true; + } + if (desiredCategoryIndex > categories.Length - 1) + { + desiredCategoryIndex = 0; + goToEndOfNextCategory = false; + } + if (desiredCategoryIndex < 0) + { + desiredCategoryIndex = categories.Length - 1; + goToEndOfNextCategory = true; + } + foreach (MPButton element in navigationPageIndicatorAllocator.elements) + { + ColorBlock colors = element.colors; + colors.colorMultiplier = 1f; + element.colors = colors; + } + if (currentPageIndex < navigationPageIndicatorAllocator.elements.Count) + { + MPButton mPButton = navigationPageIndicatorAllocator.elements[currentPageIndex]; + ColorBlock colors2 = mPButton.colors; + colors2.colorMultiplier = 2f; + mPButton.colors = colors2; + } + if (desiredCategoryIndex != currentCategoryIndex) + { + if (stateMachine.state is Idle) + { + int num = ((desiredCategoryIndex > currentCategoryIndex) ? 1 : (-1)); + stateMachine.SetNextState(new ChangeCategoryState + { + newCategoryIndex = currentCategoryIndex + num, + goToLastPage = goToEndOfNextCategory + }); + } + } + else if (desiredPageIndex != currentPageIndex && stateMachine.state is Idle) + { + int num2 = ((desiredPageIndex > currentPageIndex) ? 1 : (-1)); + stateMachine.SetNextState(new ChangeEntriesPageState + { + newNavigationPageInfo = GetCategoryPages(currentCategoryIndex)[currentPageIndex + num2], + moveDirection = new Vector2(num2, 0f) + }); + } + } + + private UserProfile LookUpUserProfile() + { + return LocalUserManager.readOnlyLocalUsersList.FirstOrDefault((LocalUser v) => v != null)?.userProfile; + } + + private GameObject BuildEntriesPage(NavigationPageInfo navigationPageInfo) + { + Entry[] entries = navigationPageInfo.entries; + CategoryDef categoryDef = navigationPageInfo.categoryDef; + GameObject gameObject = UnityEngine.Object.Instantiate(entryPagePrefab, entryPageContainer); + GridLayoutGroup component = gameObject.GetComponent(); + component.cellSize = categoryDef.iconSize; + component.constraint = GridLayoutGroup.Constraint.FixedColumnCount; + float num = entryPageContainer.rect.width - (float)component.padding.left - (float)component.padding.right; + component.constraintCount = (int)(num / (component.cellSize.x + component.spacing.x)); + UIElementAllocator uIElementAllocator = new UIElementAllocator((RectTransform)gameObject.transform, categoryDef.iconPrefab); + uIElementAllocator.AllocateElements(entries.Length); + UserProfile userProfile = LookUpUserProfile(); + ReadOnlyCollection elements = uIElementAllocator.elements; + for (int i = 0; i < elements.Count; i++) + { + RectTransform rectTransform = elements[i]; + HGButton component2 = rectTransform.GetComponent(); + Entry entry = ((i < entries.Length) ? entries[i] : null); + EntryStatus entryStatus = entry?.GetStatus(userProfile) ?? EntryStatus.None; + if (entryStatus != 0) + { + TooltipContent tooltipContent = entry.GetTooltipContent(userProfile, entryStatus); + categoryDef.initializeElementGraphics?.Invoke(rectTransform.gameObject, entry, entryStatus, userProfile); + if ((bool)component2) + { + UnityEngine.UI.Navigation navigation = component2.navigation; + navigation.mode = UnityEngine.UI.Navigation.Mode.Explicit; + int index = (i + elements.Count - 1) % elements.Count; + navigation.selectOnLeft = elements[index].GetComponent(); + int index2 = (i + elements.Count + 1) % elements.Count; + navigation.selectOnRight = elements[index2].GetComponent(); + if (i - component.constraintCount >= 0) + { + navigation.selectOnUp = elements[i - component.constraintCount].GetComponent(); + } + if (i + component.constraintCount < elements.Count) + { + navigation.selectOnDown = elements[i + component.constraintCount].GetComponent(); + } + component2.navigation = navigation; + bool flag = entryStatus >= EntryStatus.Available; + component2.interactable = true; + component2.disableGamepadClick = component2.disableGamepadClick || !flag; + component2.disablePointerClick = component2.disablePointerClick || !flag; + component2.imageOnInteractable = (flag ? component2.imageOnInteractable : null); + component2.requiredTopLayer = uiLayerKey; + component2.updateTextOnHover = true; + component2.hoverLanguageTextMeshController = hoverLanguageTextMeshController; + string titleText = tooltipContent.GetTitleText(); + string bodyText = tooltipContent.GetBodyText(); + Color titleColor = tooltipContent.titleColor; + titleColor.a = 0.2f; + component2.hoverToken = Language.GetStringFormatted("LOGBOOK_HOVER_DESCRIPTION_FORMAT", titleText, bodyText, ColorUtility.ToHtmlStringRGBA(titleColor)); + } + if (entry.viewableNode != null) + { + ViewableTag viewableTag = rectTransform.gameObject.GetComponent(); + if (!viewableTag) + { + viewableTag = rectTransform.gameObject.AddComponent(); + viewableTag.viewableVisualStyle = ViewableTag.ViewableVisualStyle.Icon; + } + viewableTag.viewableName = entry.viewableNode.fullName; + } + } + if (entryStatus >= EntryStatus.Available && (bool)component2) + { + component2.onClick.AddListener(delegate + { + ViewEntry(entry); + }); + } + if (entryStatus == EntryStatus.None) + { + if ((bool)component2) + { + component2.enabled = false; + component2.targetGraphic.color = spaceFillerColor; + } + else + { + rectTransform.GetComponent().color = spaceFillerColor; + } + for (int num2 = rectTransform.childCount - 1; num2 >= 0; num2--) + { + UnityEngine.Object.Destroy(rectTransform.GetChild(num2).gameObject); + } + } + if ((bool)component2 && i == 0) + { + component2.defaultFallbackButton = true; + } + } + gameObject.gameObject.SetActive(value: true); + GridLayoutGroup gridLayoutGroup = gameObject.GetComponent(); + Action destroyLayoutGroup = null; + int frameTimer = 2; + destroyLayoutGroup = delegate + { + int num3 = frameTimer - 1; + frameTimer = num3; + if (frameTimer <= 0) + { + gridLayoutGroup.enabled = false; + RoR2Application.onLateUpdate -= destroyLayoutGroup; + } + }; + RoR2Application.onLateUpdate += destroyLayoutGroup; + return gameObject; + } + + private void ViewEntry(Entry entry) + { + OnViewEntry.Invoke(); + LogBookPage component = pageViewerPanel.GetComponent(); + component.SetEntry(LookUpUserProfile(), entry); + component.modelPanel.SetAnglesForCharacterThumbnailForSeconds(0.5f); + ViewableTrigger.TriggerView(entry.viewableNode?.fullName); + } + + private void ReturnToNavigation() + { + navigationPanel.SetActive(value: true); + pageViewerPanel.SetActive(value: false); + } + + private static bool UnlockableExists(UnlockableDef unlockableDef) + { + return unlockableDef; + } + + private static bool IsEntryBodyWithoutLore(in Entry entry) + { + CharacterBody obj = (CharacterBody)entry.extraData; + bool flag = false; + string text = ""; + string baseNameToken = obj.baseNameToken; + if (!string.IsNullOrEmpty(baseNameToken)) + { + text = baseNameToken.Replace("_NAME", "_LORE"); + if (Language.english.TokenIsRegistered(text)) + { + flag = true; + } + } + return !flag; + } + + private static bool IsEntryPickupItemWithoutLore(in Entry entry) + { + ItemDef itemDef = ItemCatalog.GetItemDef(PickupCatalog.GetPickupDef((PickupIndex)entry.extraData).itemIndex); + return !Language.english.TokenIsRegistered(itemDef.loreToken); + } + + private static bool IsEntryPickupEquipmentWithoutLore(in Entry entry) + { + EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(PickupCatalog.GetPickupDef((PickupIndex)entry.extraData).equipmentIndex); + return !Language.english.TokenIsRegistered(equipmentDef.loreToken); + } + + private static bool CanSelectItemEntry(ItemDef itemDef, Dictionary expansionAvailability) + { + if (itemDef != null) + { + ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(itemDef.tier); + if ((bool)itemTierDef && itemTierDef.isDroppable) + { + if (!(itemDef.requiredExpansion == null) && expansionAvailability.ContainsKey(itemDef.requiredExpansion)) + { + return expansionAvailability[itemDef.requiredExpansion]; + } + return true; + } + return false; + } + return false; + } + + private static bool CanSelectEquipmentEntry(EquipmentDef equipmentDef, Dictionary expansionAvailability) + { + if (equipmentDef != null) + { + if (equipmentDef.canDrop) + { + if (!(equipmentDef.requiredExpansion == null) && expansionAvailability.ContainsKey(equipmentDef.requiredExpansion)) + { + return expansionAvailability[equipmentDef.requiredExpansion]; + } + return true; + } + return false; + } + return false; + } + + private static Entry[] BuildPickupEntries(Dictionary expansionAvailability) + { + new Entry + { + nameToken = "TOOLTIP_WIP_CONTENT_NAME", + color = Color.white, + iconTexture = LegacyResourcesAPI.Load("Textures/MiscIcons/texWIPIcon"), + getStatusImplementation = GetUnimplemented, + getTooltipContentImplementation = GetWIPTooltipContent + }; + IEnumerable first = from pickupDef in PickupCatalog.allPickups + select ItemCatalog.GetItemDef(pickupDef.itemIndex) into itemDef + where CanSelectItemEntry(itemDef, expansionAvailability) + orderby (int)(itemDef.tier + ((itemDef.tier == ItemTier.Lunar) ? 100 : 0)) + select new Entry + { + nameToken = itemDef.nameToken, + color = ColorCatalog.GetColor(itemDef.darkColorIndex), + iconTexture = itemDef.pickupIconTexture, + bgTexture = itemDef.bgIconTexture, + extraData = PickupCatalog.FindPickupIndex(itemDef.itemIndex), + modelPrefab = itemDef.pickupModelPrefab, + getStatusImplementation = GetPickupStatus, + getTooltipContentImplementation = GetPickupTooltipContent, + pageBuilderMethod = PageBuilder.SimplePickup, + isWIPImplementation = IsEntryPickupItemWithoutLore + }; + IEnumerable second = from pickupDef in PickupCatalog.allPickups + select EquipmentCatalog.GetEquipmentDef(pickupDef.equipmentIndex) into equipmentDef + where CanSelectEquipmentEntry(equipmentDef, expansionAvailability) + orderby !equipmentDef.isLunar + select new Entry + { + nameToken = equipmentDef.nameToken, + color = ColorCatalog.GetColor(equipmentDef.colorIndex), + iconTexture = equipmentDef.pickupIconTexture, + bgTexture = equipmentDef.bgIconTexture, + extraData = PickupCatalog.FindPickupIndex(equipmentDef.equipmentIndex), + modelPrefab = equipmentDef.pickupModelPrefab, + getStatusImplementation = GetPickupStatus, + getTooltipContentImplementation = GetPickupTooltipContent, + pageBuilderMethod = PageBuilder.SimplePickup, + isWIPImplementation = IsEntryPickupEquipmentWithoutLore + }; + return first.Concat(second).ToArray(); + } + + private static bool CanSelectMonsterEntry(CharacterBody characterBody, Dictionary expansionAvailability) + { + if ((bool)characterBody) + { + ExpansionRequirementComponent component = characterBody.GetComponent(); + if (!component || !component.requiredExpansion || !expansionAvailability.ContainsKey(component.requiredExpansion) || expansionAvailability[component.requiredExpansion]) + { + return UnlockableExists(characterBody.GetComponent()?.logUnlockableDef); + } + return false; + } + return false; + } + + private static Entry[] BuildMonsterEntries(Dictionary expansionAvailability) + { + Entry[] array = (from characterBody in BodyCatalog.allBodyPrefabBodyBodyComponents + where CanSelectMonsterEntry(characterBody, expansionAvailability) + orderby characterBody.baseMaxHealth + select new Entry + { + nameToken = characterBody.baseNameToken, + color = ColorCatalog.GetColor(ColorCatalog.ColorIndex.HardDifficulty), + iconTexture = characterBody.portraitIcon, + extraData = characterBody, + modelPrefab = characterBody.GetComponent()?.modelTransform?.gameObject, + getStatusImplementation = GetMonsterStatus, + getTooltipContentImplementation = GetMonsterTooltipContent, + pageBuilderMethod = PageBuilder.MonsterBody, + bgTexture = (characterBody.isChampion ? LegacyResourcesAPI.Load("Textures/ItemIcons/BG/texTier3BGIcon") : LegacyResourcesAPI.Load("Textures/ItemIcons/BG/texTier1BGIcon")), + isWIPImplementation = IsEntryBodyWithoutLore + }).ToArray(); + Dictionary dictionary = new Dictionary(); + Entry[] array2 = array; + foreach (Entry entry in array2) + { + if (!dictionary.ContainsKey(entry.nameToken)) + { + dictionary.Add(entry.nameToken, entry); + } + } + return dictionary.Values.ToArray(); + } + + private static bool CanSelectStageEntry(SceneDef sceneDef, Dictionary expansionAvailability) + { + if ((bool)sceneDef) + { + ExpansionDef requiredExpansion = sceneDef.requiredExpansion; + if (!requiredExpansion || !expansionAvailability.ContainsKey(requiredExpansion) || expansionAvailability[requiredExpansion]) + { + return sceneDef.shouldIncludeInLogbook; + } + return false; + } + return false; + } + + private static Entry[] BuildStageEntries(Dictionary expansionAvailability) + { + return (from sceneDef in SceneCatalog.allSceneDefs + where CanSelectStageEntry(sceneDef, expansionAvailability) + orderby sceneDef.stageOrder + select new Entry + { + nameToken = sceneDef.nameToken, + iconTexture = sceneDef.previewTexture, + color = ColorCatalog.GetColor(ColorCatalog.ColorIndex.Tier2ItemDark), + getStatusImplementation = GetStageStatus, + modelPrefab = sceneDef.dioramaPrefab, + getTooltipContentImplementation = GetStageTooltipContent, + pageBuilderMethod = PageBuilder.Stage, + extraData = sceneDef, + isWIPImplementation = delegate(in Entry entry) + { + return !Language.english.TokenIsRegistered(((SceneDef)entry.extraData).loreToken); + } + }).ToArray(); + } + + private static bool CanSelectSurvivorBodyEntry(CharacterBody body, Dictionary expansionAvailability) + { + if ((bool)body) + { + ExpansionRequirementComponent component = body.GetComponent(); + if ((bool)component && (bool)component.requiredExpansion && expansionAvailability.ContainsKey(component.requiredExpansion)) + { + return expansionAvailability[component.requiredExpansion]; + } + return true; + } + return false; + } + + private static Entry[] BuildSurvivorEntries(Dictionary expansionAvailability) + { + return (from survivorDef in SurvivorCatalog.orderedSurvivorDefs + select BodyCatalog.GetBodyPrefabBodyComponent(SurvivorCatalog.GetBodyIndexFromSurvivorIndex(survivorDef.survivorIndex)) into body + where CanSelectSurvivorBodyEntry(body, expansionAvailability) + select body into characterBody + select new Entry + { + nameToken = characterBody.baseNameToken, + color = ColorCatalog.GetColor(ColorCatalog.ColorIndex.NormalDifficulty), + iconTexture = characterBody.portraitIcon, + bgTexture = LegacyResourcesAPI.Load("Textures/ItemIcons/BG/texSurvivorBGIcon"), + extraData = characterBody, + modelPrefab = characterBody.GetComponent()?.modelTransform?.gameObject, + getStatusImplementation = GetSurvivorStatus, + getTooltipContentImplementation = GetSurvivorTooltipContent, + pageBuilderMethod = PageBuilder.SurvivorBody, + isWIPImplementation = IsEntryBodyWithoutLore + }).ToArray(); + } + + private static bool CanSelectAchievementEntry(AchievementDef achievementDef, Dictionary expansionAvailability) + { + if (achievementDef != null) + { + ExpansionDef expansionDefForUnlockable = UnlockableCatalog.GetExpansionDefForUnlockable(UnlockableCatalog.GetUnlockableDef(achievementDef.unlockableRewardIdentifier)?.index ?? UnlockableIndex.None); + if ((bool)expansionDefForUnlockable && expansionAvailability.ContainsKey(expansionDefForUnlockable)) + { + return expansionAvailability[expansionDefForUnlockable]; + } + return true; + } + return false; + } + + private static Entry[] BuildAchievementEntries(Dictionary expansionAvailability) + { + return (from achievementDef in AchievementManager.allAchievementDefs + where CanSelectAchievementEntry(achievementDef, expansionAvailability) + select new Entry + { + nameToken = achievementDef.nameToken, + color = ColorCatalog.GetColor(ColorCatalog.ColorIndex.NormalDifficulty), + iconTexture = achievementDef.GetAchievedIcon()?.texture, + extraData = achievementDef, + modelPrefab = null, + getStatusImplementation = GetAchievementStatus, + getTooltipContentImplementation = GetAchievementTooltipContent + }).ToArray(); + } + + private static Entry[] BuildProfileEntries(UserProfile viewerProfile) + { + List entries = new List(); + if (true) + { + foreach (string availableProfileName in PlatformSystems.saveSystem.GetAvailableProfileNames()) + { + AddProfileStatsEntry(PlatformSystems.saveSystem.GetProfile(availableProfileName)); + } + } + else if (viewerProfile != null) + { + AddProfileStatsEntry(viewerProfile); + } + return entries.ToArray(); + void AddProfileStatsEntry(UserProfile userProfile) + { + Entry item = new Entry + { + pageBuilderMethod = PageBuilder.StatsPanel, + getStatusImplementation = delegate + { + return EntryStatus.Available; + }, + extraData = userProfile, + getDisplayNameImplementation = delegate(in Entry entry, UserProfile _viewerProfile) + { + return ((UserProfile)entry.extraData).name; + }, + iconTexture = userProfile.portraitTexture + }; + entries.Add(item); + } + } + + private static Entry[] BuildMorgueEntries(UserProfile viewerProfile) + { + List entries = CollectionPool>.RentCollection(); + List list = CollectionPool>.RentCollection(); + MorgueManager.LoadHistoryRunReports(list); + foreach (RunReport item2 in list) + { + AddRunReportEntry(item2); + } + CollectionPool>.ReturnCollection(list); + Entry[] result = entries.ToArray(); + CollectionPool>.ReturnCollection(entries); + return result; + void AddRunReportEntry(RunReport runReport) + { + GetPrimaryPlayerInfo(runReport, out var _, out var primaryPlayerBody3); + Entry item = new Entry + { + pageBuilderMethod = PageBuilder.RunReportPanel, + getStatusImplementation = GetEntryStatus, + extraData = runReport, + getDisplayNameImplementation = GetDisplayName, + getTooltipContentImplementation = GetTooltipContent, + iconTexture = primaryPlayerBody3?.portraitIcon + }; + entries.Add(item); + } + static string GetDisplayName(in Entry entry, UserProfile _viewerProfile) + { + return ((RunReport)entry.extraData).snapshotTimeUtc.ToLocalTime().ToString("G", CultureInfo.CurrentCulture); + } + static EntryStatus GetEntryStatus(in Entry entry, UserProfile _viewerProfile) + { + return EntryStatus.Available; + } + void GetPrimaryPlayerInfo(RunReport _runReport, out RunReport.PlayerInfo primaryPlayerInfo, out CharacterBody primaryPlayerBody) + { + primaryPlayerInfo = _runReport.FindPlayerInfo(viewerProfile) ?? _runReport.FindFirstPlayerInfo(); + primaryPlayerBody = BodyCatalog.GetBodyPrefabBodyComponent(primaryPlayerInfo?.bodyIndex ?? BodyIndex.None); + } + TooltipContent GetTooltipContent(in Entry entry, UserProfile _viewerProfile, EntryStatus entryStatus) + { + RunReport runReport2 = (RunReport)entry.extraData; + GetPrimaryPlayerInfo(runReport2, out var _, out var primaryPlayerBody2); + TooltipContent result2 = default(TooltipContent); + result2.overrideTitleText = Language.GetStringFormatted("LOGBOOK_ENTRY_RUNREPORT_TOOLTIP_TITLE_FORMAT", runReport2.snapshotTimeUtc.ToLocalTime().ToString("G", CultureInfo.CurrentCulture)); + result2.overrideBodyText = Language.GetStringFormatted("LOGBOOK_ENTRY_RUNREPORT_TOOLTIP_BODY_FORMAT", Language.GetString(primaryPlayerBody2?.baseNameToken ?? string.Empty), Language.GetString(runReport2.gameMode?.nameToken ?? string.Empty), Language.GetString(runReport2.gameEnding?.endingTextToken ?? string.Empty)); + return result2; + } + } + + private static IEnumerator WaitForBuildingStaticData() + { + IsStaticDataReady = false; + Dictionary expansionAvailability = new Dictionary(); + List list = new List(); + foreach (ExpansionDef expansionDef in ExpansionCatalog.expansionDefs) + { + expansionAvailability.Add(expansionDef, !expansionDef.requiredEntitlement || EntitlementManager.localUserEntitlementTracker.AnyUserHasEntitlement(expansionDef.requiredEntitlement)); + if (expansionAvailability[expansionDef]) + { + list.Add(expansionDef.requiredEntitlement); + } + } + if (lastBuiltEntitlements != null && lastBuiltEntitlements.SequenceEqual(list)) + { + lastBuiltEntitlements = list; + IsStaticDataReady = true; + yield break; + } + lastBuiltEntitlements = list; + yield return null; + Entry[] pickupEntries = BuildPickupEntries(expansionAvailability); + yield return null; + Entry[] monsterEntries = BuildMonsterEntries(expansionAvailability); + yield return null; + Entry[] stageEntries = BuildStageEntries(expansionAvailability); + yield return null; + Entry[] survivorEntries = BuildSurvivorEntries(expansionAvailability); + yield return null; + Entry[] achievementEntries = BuildAchievementEntries(expansionAvailability); + yield return null; + categories = new CategoryDef[7] + { + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_ITEMANDEQUIPMENT", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/ItemEntryIcon"), + buildEntries = (UserProfile viewerProfile) => pickupEntries, + navButtons = new CategoryDef.NavButtons + { + navigate = "LOGBOOK_ZOOMINOUT" + } + }, + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_MONSTER", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/MonsterEntryIcon"), + buildEntries = (UserProfile viewerProfile) => monsterEntries, + navButtons = new CategoryDef.NavButtons + { + navigate = "LOGBOOK_ZOOMINOUT" + } + }, + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_STAGE", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/StageEntryIcon"), + buildEntries = (UserProfile viewerProfile) => stageEntries + }, + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_SURVIVOR", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/SurvivorEntryIcon"), + buildEntries = (UserProfile viewerProfile) => survivorEntries + }, + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_ACHIEVEMENTS", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/AchievementEntryIcon"), + buildEntries = (UserProfile viewerProfile) => achievementEntries, + initializeElementGraphics = CategoryDef.InitializeChallenge + }, + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_STATS", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/StatsEntryIcon"), + buildEntries = BuildProfileEntries, + initializeElementGraphics = CategoryDef.InitializeStats, + navButtons = new CategoryDef.NavButtons + { + scroll = "", + rotate = "LOGBOOK_PAN" + } + }, + new CategoryDef + { + nameToken = "LOGBOOK_CATEGORY_MORGUE", + iconPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/MorgueEntryIcon"), + buildEntries = BuildMorgueEntries, + initializeElementGraphics = CategoryDef.InitializeMorgue, + navButtons = new CategoryDef.NavButtons + { + rotate = "", + navigate = "" + } + } + }; + RegisterViewables(categories); + availability.MakeAvailable(); + IsStaticDataReady = true; + EntitlementManager.UpdateLocalUsersEntitlements(); + } + + [ConCommand(commandName = "logbook_list_unfinished_lore", flags = ConVarFlags.None, helpText = "Prints all logbook entries which still have undefined lore.")] + private static void CCLogbookListUnfinishedLore(ConCommandArgs args) + { + List list = new List(); + CategoryDef[] array = categories; + for (int i = 0; i < array.Length; i++) + { + Entry[] array2 = array[i].BuildEntries(args.GetSenderLocalUser()?.userProfile); + foreach (Entry entry in array2) + { + string text = ""; + if (entry.extraData is UnityEngine.Object @object) + { + text = @object.name; + } + if (entry.isWip) + { + list.Add(entry.extraData?.GetType()?.Name + " \"" + text + "\" \"" + Language.GetString(entry.nameToken) + "\""); + } + } + } + args.Log(string.Join("\n", list)); + } + + private static void RegisterViewables(CategoryDef[] categoriesToGenerateFrom) + { + ViewablesCatalog.Node node = new ViewablesCatalog.Node("Logbook", isFolder: true); + CategoryDef[] array = categories; + foreach (CategoryDef obj in array) + { + ViewablesCatalog.Node parent = (obj.viewableNode = new ViewablesCatalog.Node(obj.nameToken, isFolder: true, node)); + Entry[] array2 = obj.BuildEntries(null); + foreach (Entry entry in array2) + { + string nameToken = entry.nameToken; + ViewablesCatalog.Node entryNode; + AchievementDef achievementDef; + bool hasPrereq; + if (!entry.isWip && !(nameToken == "TOOLTIP_WIP_CONTENT_NAME") && !string.IsNullOrEmpty(nameToken)) + { + entryNode = new ViewablesCatalog.Node(nameToken, isFolder: false, parent); + object extraData = entry.extraData; + achievementDef = extraData as AchievementDef; + if (achievementDef != null) + { + hasPrereq = !string.IsNullOrEmpty(achievementDef.prerequisiteAchievementIdentifier); + entryNode.shouldShowUnviewed = Check; + } + else + { + entryNode.shouldShowUnviewed = Check; + } + entry.viewableNode = entryNode; + } + bool Check(UserProfile userProfile) + { + if (userProfile.HasViewedViewable(entryNode.fullName)) + { + return false; + } + if (userProfile.HasAchievement(achievementDef.identifier)) + { + return false; + } + if (hasPrereq) + { + return userProfile.HasAchievement(achievementDef.prerequisiteAchievementIdentifier); + } + return true; + } + bool Check(UserProfile viewerProfile) + { + if (viewerProfile.HasViewedViewable(entryNode.fullName)) + { + return false; + } + return entry.GetStatus(viewerProfile) == EntryStatus.Available; + } + } + } + ViewablesCatalog.AddNodeToRoot(node); + LogBookController.OnViewablesRegistered?.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/LogBookPage.cs b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/LogBookPage.cs new file mode 100644 index 0000000..9c03eca --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/LogBookPage.cs @@ -0,0 +1,74 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.UI.LogBook; + +public class LogBookPage : MonoBehaviour +{ + public RawImage iconImage; + + public ModelPanel modelPanel; + + public TextMeshProUGUI titleText; + + public TextMeshProUGUI categoryText; + + public TextMeshProUGUI pageNumberText; + + public RectTransform contentContainer; + + private PageBuilder pageBuilder; + + [Header("Buttons")] + public GameObject scroll; + + public LanguageTextMeshController scrollLabel; + + public GameObject back; + + public LanguageTextMeshController backLabel; + + public GameObject navigate; + + public LanguageTextMeshController navigateLabel; + + public GameObject rotate; + + public LanguageTextMeshController rotateLabel; + + public void SetEntry(UserProfile userProfile, Entry entry) + { + pageBuilder?.Destroy(); + pageBuilder = new PageBuilder(); + pageBuilder.container = contentContainer; + pageBuilder.entry = entry; + pageBuilder.userProfile = userProfile; + entry.pageBuilderMethod?.Invoke(pageBuilder); + iconImage.texture = entry.iconTexture; + titleText.text = entry.GetDisplayName(userProfile); + categoryText.text = entry.GetCategoryDisplayName(userProfile); + modelPanel.modelPrefab = entry.modelPrefab; + modelPanel.transform.parent.parent.gameObject.SetActive(entry.modelPrefab); + UpdateButtons(entry.category.navButtons); + } + + private void UpdateButtons(CategoryDef.NavButtons buttons) + { + RelabelButton(scroll, scrollLabel, buttons.scroll); + RelabelButton(back, backLabel, buttons.back); + RelabelButton(navigate, navigateLabel, buttons.navigate); + RelabelButton(rotate, rotateLabel, buttons.rotate); + } + + private void RelabelButton(GameObject button, LanguageTextMeshController label, string text) + { + if (text == "") + { + button.gameObject.SetActive(value: false); + return; + } + button.gameObject.SetActive(value: true); + label.token = text; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/PageBuilder.cs b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/PageBuilder.cs new file mode 100644 index 0000000..a9fb036 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.LogBook/PageBuilder.cs @@ -0,0 +1,528 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Numerics; +using System.Text; +using HG; +using RoR2.Stats; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.UI.LogBook; + +public class PageBuilder +{ + private static readonly StringBuilder sharedStringBuilder = new StringBuilder(); + + public UserProfile userProfile; + + public RectTransform container; + + public Entry entry; + + public readonly List managedObjects = new List(); + + private StatSheet statSheet => userProfile.statSheet; + + public void Destroy() + { + foreach (GameObject managedObject in managedObjects) + { + UnityEngine.Object.Destroy(managedObject); + } + } + + public void AddSimpleTextPanel(string text) + { + AddPrefabInstance(LegacyResourcesAPI.Load("Prefabs/UI/Logbook/SimpleTextPanel")).GetComponent().FindChild("MainLabel").GetComponent() + .text = text; + } + + public GameObject AddPrefabInstance(GameObject prefab) + { + GameObject gameObject = UnityEngine.Object.Instantiate(prefab, container); + managedObjects.Add(gameObject); + return gameObject; + } + + public void AddSimpleTextPanel(params string[] textLines) + { + AddSimpleTextPanel(string.Join("\n", textLines)); + } + + public void AddSimplePickup(PickupIndex pickupIndex) + { + PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); + ItemIndex itemIndex = pickupDef?.itemIndex ?? ItemIndex.None; + EquipmentIndex equipmentIndex = pickupDef?.equipmentIndex ?? EquipmentIndex.None; + string token = null; + if (itemIndex != ItemIndex.None) + { + ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex); + AddDescriptionPanel(Language.GetString(itemDef.descriptionToken)); + token = itemDef.loreToken; + ulong statValueULong = statSheet.GetStatValueULong(PerItemStatDef.totalCollected.FindStatDef(itemIndex)); + ulong statValueULong2 = statSheet.GetStatValueULong(PerItemStatDef.highestCollected.FindStatDef(itemIndex)); + string stringFormatted = Language.GetStringFormatted("GENERIC_PREFIX_FOUND", statValueULong); + string stringFormatted2 = Language.GetStringFormatted("ITEM_PREFIX_STACKCOUNT", statValueULong2); + AddSimpleTextPanel(stringFormatted, stringFormatted2); + } + else if (equipmentIndex != EquipmentIndex.None) + { + EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex); + AddDescriptionPanel(Language.GetString(equipmentDef.descriptionToken)); + token = equipmentDef.loreToken; + string stringFormatted3 = Language.GetStringFormatted("EQUIPMENT_PREFIX_COOLDOWN", equipmentDef.cooldown); + string stringFormatted4 = Language.GetStringFormatted("EQUIPMENT_PREFIX_TOTALTIMEHELD", statSheet.GetStatDisplayValue(PerEquipmentStatDef.totalTimeHeld.FindStatDef(equipmentIndex))); + string stringFormatted5 = Language.GetStringFormatted("EQUIPMENT_PREFIX_USECOUNT", statSheet.GetStatDisplayValue(PerEquipmentStatDef.totalTimesFired.FindStatDef(equipmentIndex))); + AddSimpleTextPanel(stringFormatted3); + AddSimpleTextPanel(stringFormatted4, stringFormatted5); + } + AddNotesPanel(Language.IsTokenInvalid(token) ? Language.GetString("EARLY_ACCESS_LORE") : Language.GetString(token)); + } + + public void AddDescriptionPanel(string content) + { + AddSimpleTextPanel(Language.GetStringFormatted("DESCRIPTION_PREFIX_FORMAT", content)); + } + + public void AddNotesPanel(string content) + { + AddSimpleTextPanel(Language.GetStringFormatted("NOTES_PREFIX_FORMAT", content)); + } + + public void AddBodyStatsPanel(CharacterBody bodyPrefabComponent) + { + float baseMaxHealth = bodyPrefabComponent.baseMaxHealth; + float levelMaxHealth = bodyPrefabComponent.levelMaxHealth; + float baseDamage = bodyPrefabComponent.baseDamage; + float levelDamage = bodyPrefabComponent.levelDamage; + float baseArmor = bodyPrefabComponent.baseArmor; + float baseRegen = bodyPrefabComponent.baseRegen; + float levelRegen = bodyPrefabComponent.levelRegen; + float baseMoveSpeed = bodyPrefabComponent.baseMoveSpeed; + AddSimpleTextPanel(Language.GetStringFormatted("BODY_HEALTH_FORMAT", Language.GetStringFormatted("BODY_STATS_FORMAT", baseMaxHealth.ToString(), levelMaxHealth.ToString())) + "\n" + Language.GetStringFormatted("BODY_DAMAGE_FORMAT", Language.GetStringFormatted("BODY_STATS_FORMAT", baseDamage.ToString(), levelDamage.ToString())) + "\n" + ((baseRegen >= Mathf.Epsilon) ? (Language.GetStringFormatted("BODY_REGEN_FORMAT", Language.GetStringFormatted("BODY_STATS_FORMAT", baseRegen.ToString(), levelRegen.ToString())) + "\n") : "") + Language.GetStringFormatted("BODY_MOVESPEED_FORMAT", baseMoveSpeed) + "\n" + Language.GetStringFormatted("BODY_ARMOR_FORMAT", baseArmor.ToString())); + } + + public void AddMonsterPanel(CharacterBody bodyPrefabComponent) + { + ulong statValueULong = statSheet.GetStatValueULong(PerBodyStatDef.killsAgainst, bodyPrefabComponent.gameObject.name); + ulong statValueULong2 = statSheet.GetStatValueULong(PerBodyStatDef.killsAgainstElite, bodyPrefabComponent.gameObject.name); + ulong statValueULong3 = statSheet.GetStatValueULong(PerBodyStatDef.deathsFrom, bodyPrefabComponent.gameObject.name); + string stringFormatted = Language.GetStringFormatted("MONSTER_PREFIX_KILLED", statValueULong); + string stringFormatted2 = Language.GetStringFormatted("MONSTER_PREFIX_ELITESKILLED", statValueULong2); + string stringFormatted3 = Language.GetStringFormatted("MONSTER_PREFIX_DEATH", statValueULong3); + AddSimpleTextPanel(stringFormatted, stringFormatted2, stringFormatted3); + } + + public void AddSurvivorPanel(CharacterBody bodyPrefabComponent) + { + string statDisplayValue = statSheet.GetStatDisplayValue(PerBodyStatDef.longestRun.FindStatDef(bodyPrefabComponent.name)); + ulong statValueULong = statSheet.GetStatValueULong(PerBodyStatDef.timesPicked.FindStatDef(bodyPrefabComponent.name)); + ulong statValueULong2 = statSheet.GetStatValueULong(StatDef.totalGamesPlayed); + double num = 0.0; + if (statValueULong2 != 0L) + { + num = (double)statValueULong / (double)statValueULong2 * 100.0; + } + sharedStringBuilder.Clear(); + sharedStringBuilder.AppendLine(Language.GetStringFormatted("SURVIVOR_PREFIX_LONGESTRUN", statDisplayValue)); + sharedStringBuilder.AppendLine(Language.GetStringFormatted("SURVIVOR_PREFIX_TIMESPICKED", statValueULong)); + sharedStringBuilder.AppendLine(Language.GetStringFormatted("SURVIVOR_PREFIX_PICKPERCENTAGE", num)); + AddSimpleTextPanel(sharedStringBuilder.ToString()); + } + + public void AddSimpleBody(CharacterBody bodyPrefabComponent) + { + AddBodyStatsPanel(bodyPrefabComponent); + } + + public void AddBodyLore(CharacterBody characterBody) + { + bool flag = false; + string token = ""; + string baseNameToken = characterBody.baseNameToken; + if (!string.IsNullOrEmpty(baseNameToken)) + { + token = baseNameToken.Replace("_NAME", "_LORE"); + if (!Language.IsTokenInvalid(token)) + { + flag = true; + } + } + if (flag) + { + AddNotesPanel(Language.GetString(token)); + } + else + { + AddNotesPanel(Language.GetString("EARLY_ACCESS_LORE")); + } + } + + public void AddStagePanel(SceneDef sceneDef) + { + string statDisplayValue = userProfile.statSheet.GetStatDisplayValue(PerStageStatDef.totalTimesVisited.FindStatDef(sceneDef.baseSceneName)); + string statDisplayValue2 = userProfile.statSheet.GetStatDisplayValue(PerStageStatDef.totalTimesCleared.FindStatDef(sceneDef.baseSceneName)); + string stringFormatted = Language.GetStringFormatted("STAGE_PREFIX_TOTALTIMESVISITED", statDisplayValue); + string stringFormatted2 = Language.GetStringFormatted("STAGE_PREFIX_TOTALTIMESCLEARED", statDisplayValue2); + sharedStringBuilder.Clear(); + sharedStringBuilder.Append(stringFormatted); + sharedStringBuilder.Append("\n"); + sharedStringBuilder.Append(stringFormatted2); + AddSimpleTextPanel(sharedStringBuilder.ToString()); + } + + public void AddPieChart(PieChartMeshController.SliceInfo[] sliceInfos) + { + GameObject gameObject = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/UI/PieChartPanel"), container); + gameObject.GetComponent().SetSlices(sliceInfos); + managedObjects.Add(gameObject); + } + + public static void Stage(PageBuilder builder) + { + SceneDef sceneDef = (SceneDef)builder.entry.extraData; + builder.AddStagePanel(sceneDef); + builder.AddNotesPanel(Language.IsTokenInvalid(sceneDef.loreToken) ? Language.GetString("EARLY_ACCESS_LORE") : Language.GetString(sceneDef.loreToken)); + } + + public static void SimplePickup(PageBuilder builder) + { + builder.AddSimplePickup((PickupIndex)builder.entry.extraData); + } + + public static void SimpleBody(PageBuilder builder) + { + builder.AddSimpleBody((CharacterBody)builder.entry.extraData); + } + + public static void MonsterBody(PageBuilder builder) + { + CharacterBody characterBody = (CharacterBody)builder.entry.extraData; + builder.AddSimpleBody(characterBody); + builder.AddMonsterPanel(characterBody); + builder.AddBodyLore(characterBody); + } + + public static void SurvivorBody(PageBuilder builder) + { + CharacterBody characterBody = (CharacterBody)builder.entry.extraData; + builder.AddSimpleBody(characterBody); + builder.AddSurvivorPanel(characterBody); + builder.AddBodyLore(characterBody); + } + + public static void StatsPanel(PageBuilder builder) + { + UserProfile userProfile = (UserProfile)builder.entry.extraData; + GameCompletionStatsHelper gameCompletionStatsHelper = new GameCompletionStatsHelper(); + StatSheet statSheet = userProfile.statSheet; + CalcAllBodyStatTotalDouble(PerBodyStatDef.totalTimeAlive); + _ = (double)CalcAllBodyStatTotalULong(PerBodyStatDef.timesPicked); + double value = (double)CalcAllBodyStatTotalULong(PerBodyStatDef.totalWins); + _ = (double)CalcAllBodyStatTotalULong(PerBodyStatDef.deathsAs); + ChildLocator component = builder.AddPrefabInstance(LegacyResourcesAPI.Load("Prefabs/UI/Logbook/ProfileStatsPanel")).GetComponent(); + RectTransform rectTransform = (RectTransform)component.FindChild("CharacterPieChart"); + RectTransform rectTransform2 = (RectTransform)component.FindChild("CompletionBarPanel"); + RectTransform rectTransform3 = (RectTransform)component.FindChild("CompletionLabel"); + RectTransform rectTransform4 = (RectTransform)component.FindChild("CharacterStatsCarousel"); + RectTransform rectTransform5 = (RectTransform)component.FindChild("TotalsStatsList"); + RectTransform rectTransform6 = (RectTransform)component.FindChild("RecordsStatsList"); + RectTransform rectTransform7 = (RectTransform)component.FindChild("MiscStatsList"); + RectTransform rectTransform8 = (RectTransform)component.FindChild("CompletionStatsList"); + PieChartMeshController characterPieChartMeshController = rectTransform.GetComponent(); + CarouselNavigationController carousel = rectTransform4.GetComponent(); + List statNames = new List(); + List callbacks = new List(); + AddPerBodyStat(PerBodyStatDef.totalWins); + AddPerBodyStat(PerBodyStatDef.timesPicked); + AddPerBodyStat(PerBodyStatDef.totalTimeAlive); + AddPerBodyStat(PerBodyStatDef.longestRun); + AddPerBodyStat(PerBodyStatDef.deathsAs); + AddPerBodyStat(PerBodyStatDef.damageDealtAs); + AddPerBodyStat(PerBodyStatDef.damageTakenAs); + AddPerBodyStat(PerBodyStatDef.damageDealtTo); + AddPerBodyStat(PerBodyStatDef.damageTakenFrom); + AddPerBodyStat(PerBodyStatDef.killsAgainst); + AddPerBodyStat(PerBodyStatDef.killsAgainstElite); + AddPerBodyStat(PerBodyStatDef.deathsFrom); + AddPerBodyStat(PerBodyStatDef.minionDamageDealtAs); + AddPerBodyStat(PerBodyStatDef.minionKillsAs); + AddPerBodyStat(PerBodyStatDef.killsAs); + carousel.onPageChangeSubmitted += OnPageChangeSubmitted; + carousel.SetDisplayData(new CarouselNavigationController.DisplayData(statNames.Count, 0)); + OnPageChangeSubmitted(0); + GameObject statStripPrefab = LegacyResourcesAPI.Load("Prefabs/UI/Logbook/LogbookStatStrip"); + StatDef statDef2 = PerBodyStatDef.longestRun.FindStatDef(statSheet.FindBodyWithHighestStat(PerBodyStatDef.longestRun)) ?? PerBodyStatDef.longestRun.FindStatDef(BodyCatalog.FindBodyIndex("CommandoBody")); + CharacterBody bodyPrefabBodyComponent = BodyCatalog.GetBodyPrefabBodyComponent(statSheet.FindBodyWithHighestStat(PerBodyStatDef.deathsFrom)); + EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(statSheet.FindEquipmentWithHighestStat(PerEquipmentStatDef.totalTimeHeld)); + (string, string, Texture)[] array = new(string, string, Texture)[20]; + (string, string, Texture2D) tuple = StatStripDataFromStatDef(StatDef.totalGamesPlayed); + array[0] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalTimeAlive); + array[1] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalDeaths); + array[2] = (tuple.Item1, tuple.Item2, tuple.Item3); + array[3] = (Language.GetString("STATNAME_TOTALWINS"), TextSerialization.ToStringNumeric(value), null); + tuple = StatStripDataFromStatDef(StatDef.totalKills); + array[4] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalEliteKills); + array[5] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalDamageDealt); + array[6] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalStagesCompleted); + array[7] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalDamageTaken); + array[8] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalHealthHealed); + array[9] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.goldCollected); + array[10] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalDistanceTraveled); + array[11] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalPurchases); + array[12] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalBloodPurchases); + array[13] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalDronesPurchased); + array[14] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalTurretsPurchased); + array[15] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalCrocoInfectionsInflicted); + array[16] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalMinionDamageDealt); + array[17] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalMinionKills); + array[18] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.totalDeathsWhileBurning); + array[19] = (tuple.Item1, tuple.Item2, tuple.Item3); + SetStats(rectTransform5, array); + (string, string, Texture)[] obj = new(string, string, Texture)[6] + { + (Language.GetString("STATNAME_LONGESTRUN"), statSheet.GetStatDisplayValue(statDef2), null), + default((string, string, Texture)), + default((string, string, Texture)), + default((string, string, Texture)), + default((string, string, Texture)), + default((string, string, Texture)) + }; + tuple = StatStripDataFromStatDef(StatDef.highestStagesCompleted); + obj[1] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.highestLevel); + obj[2] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.highestDamageDealt); + obj[3] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.maxGoldCollected); + obj[4] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromStatDef(StatDef.highestPurchases); + obj[5] = (tuple.Item1, tuple.Item2, tuple.Item3); + SetStats(rectTransform6, obj); + SetStats(rectTransform7, new(string, string, Texture)[2] + { + (Language.GetString("STATNAME_NEMESIS"), bodyPrefabBodyComponent ? Language.GetString(bodyPrefabBodyComponent.baseNameToken) : string.Empty, bodyPrefabBodyComponent ? bodyPrefabBodyComponent.portraitIcon : null), + (Language.GetString("STATNAME_FAVORITEEQUIPMENT"), (equipmentDef != null) ? Language.GetString(equipmentDef.nameToken) : string.Empty, equipmentDef?.pickupIconTexture) + }); + (string, string, Texture)[] array2 = new(string, string, Texture)[5]; + tuple = StatStripDataFromCompletionFraction("STATNAME_COMPLETION_ACHIEVEMENTS", gameCompletionStatsHelper.GetAchievementCompletion(userProfile)); + array2[0] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromCompletionFraction("STATNAME_COMPLETION_COLLECTIBLES", gameCompletionStatsHelper.GetCollectibleCompletion(userProfile)); + array2[1] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromCompletionFraction("STATNAME_COMPLETION_PICKUPDISCOVERY", gameCompletionStatsHelper.GetPickupEncounterCompletion(userProfile)); + array2[2] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromCompletionFraction("STATNAME_COMPLETION_SURVIVORSPICKED", gameCompletionStatsHelper.GetSurvivorPickCompletion(userProfile)); + array2[3] = (tuple.Item1, tuple.Item2, tuple.Item3); + tuple = StatStripDataFromCompletionFraction("STATNAME_COMPLETION_SURVIVORSWON", gameCompletionStatsHelper.GetSurvivorWinCompletion(userProfile)); + array2[4] = (tuple.Item1, tuple.Item2, tuple.Item3); + SetStats(rectTransform8, array2); + IntFraction value2 = gameCompletionStatsHelper.GetTotalCompletion(userProfile); + float num = (float)value2; + UnityEngine.Vector2 anchorMax = rectTransform2.anchorMax; + anchorMax.x = num; + rectTransform2.anchorMax = anchorMax; + rectTransform3.GetComponent().SetText($"{num:0%}"); + void AddLine(StatDef statDef, string statNameToken, double? allBodyTotal) + { + string @string = Language.GetString("STAT_NAME_VALUE_FORMAT"); + string statDisplayValue = statSheet.GetStatDisplayValue(statDef); + P_3.bodyTextStringBuilder.AppendFormat(@string, Language.GetString(statNameToken), statDisplayValue); + if (allBodyTotal.HasValue) + { + double statValueAsDouble = statSheet.GetStatValueAsDouble(statDef); + double num2 = 0.0; + if (allBodyTotal != 0.0) + { + num2 = statValueAsDouble / allBodyTotal.Value; + } + P_3.bodyTextStringBuilder.Append(" ").AppendFormat(P_3.rateFormat, num2); + } + P_3.bodyTextStringBuilder.AppendLine(); + } + void AddLineFromPerBodyStat(PerBodyStatDef perBodyStatDef, double? total) + { + if (!total.HasValue) + { + total = CalcAllBodyStatTotalDouble(perBodyStatDef); + } + StatDef statDef3 = perBodyStatDef.FindStatDef(P_2.bodyIndex); + AddLine(statDef3, perBodyStatDef.nameToken, total); + } + void AddPerBodyStat(PerBodyStatDef perBodyStatDef) + { + statNames.Add(Language.GetString(perBodyStatDef.nameToken)); + callbacks.Add(Callback); + void Callback() + { + BuildCharacterPieChart(characterPieChartMeshController, (BodyIndex bodyIndex) => GetStatWeight(perBodyStatDef.FindStatDef(bodyIndex))); + } + } + TooltipContent BuildBodyTooltipContent(BodyIndex bodyIndex, Color bodyColor) + { + CharacterBody bodyPrefabBodyComponent2 = BodyCatalog.GetBodyPrefabBodyComponent(bodyIndex); + StringBuilder bodyTextStringBuilder = HG.StringBuilderPool.RentStringBuilder(); + string rateFormat = Language.GetString("PERCENT_FORMAT_PARENTHESES"); + AddLineFromPerBodyStat(PerBodyStatDef.timesPicked, null); + AddLineFromPerBodyStat(PerBodyStatDef.totalTimeAlive, null); + AddLineFromPerBodyStat(PerBodyStatDef.longestRun, null); + AddLineFromPerBodyStat(PerBodyStatDef.totalWins, null); + AddLineFromPerBodyStat(PerBodyStatDef.deathsAs, null); + AddLineFromPerBodyStat(PerBodyStatDef.damageDealtAs, null); + AddLineFromPerBodyStat(PerBodyStatDef.damageTakenAs, null); + AddLineFromPerBodyStat(PerBodyStatDef.damageDealtTo, null); + AddLineFromPerBodyStat(PerBodyStatDef.damageTakenFrom, null); + AddLineFromPerBodyStat(PerBodyStatDef.killsAgainst, null); + AddLineFromPerBodyStat(PerBodyStatDef.killsAgainstElite, null); + AddLineFromPerBodyStat(PerBodyStatDef.deathsFrom, null); + AddLineFromPerBodyStat(PerBodyStatDef.minionDamageDealtAs, null); + AddLineFromPerBodyStat(PerBodyStatDef.minionKillsAs, null); + AddLineFromPerBodyStat(PerBodyStatDef.killsAs, null); + TooltipContent tooltipContent = default(TooltipContent); + tooltipContent.titleToken = bodyPrefabBodyComponent2.baseNameToken; + tooltipContent.titleColor = bodyColor; + tooltipContent.overrideBodyText = bodyTextStringBuilder.ToString(); + TooltipContent result3 = tooltipContent; + HG.StringBuilderPool.ReturnStringBuilder(bodyTextStringBuilder); + return result3; + } + void BuildCharacterPieChart(PieChartMeshController pieChartMeshController, Func bodyWeightGetter) + { + List list = new List(); + for (BodyIndex bodyIndex2 = (BodyIndex)0; (int)bodyIndex2 < BodyCatalog.bodyCount; bodyIndex2++) + { + float num4 = bodyWeightGetter(bodyIndex2); + if (num4 != 0f) + { + PieChartMeshController.SliceInfo item4 = default(PieChartMeshController.SliceInfo); + item4.color = GetBodyColor(bodyIndex2); + item4.weight = num4; + item4.tooltipContent = BuildBodyTooltipContent(bodyIndex2, item4.color); + list.Add(item4); + } + } + pieChartMeshController.SetSlices(list.OrderBy((PieChartMeshController.SliceInfo slice) => 0f - slice.weight).ToArray()); + } + double CalcAllBodyStatTotalDouble(PerBodyStatDef perBodyStatDef) + { + double num5 = 0.0; + for (BodyIndex bodyIndex4 = (BodyIndex)0; (int)bodyIndex4 < BodyCatalog.bodyCount; bodyIndex4++) + { + num5 += statSheet.GetStatValueAsDouble(perBodyStatDef.FindStatDef(bodyIndex4)); + } + return num5; + } + BigInteger CalcAllBodyStatTotalULong(PerBodyStatDef perBodyStatDef) + { + BigInteger result4 = 0; + for (BodyIndex bodyIndex3 = (BodyIndex)0; (int)bodyIndex3 < BodyCatalog.bodyCount; bodyIndex3++) + { + result4 += (BigInteger)statSheet.GetStatValueULong(perBodyStatDef.FindStatDef(bodyIndex3)); + } + return result4; + } + static Color GetBodyColor(BodyIndex bodyIndex) + { + CharacterBody bodyPrefabBodyComponent3 = BodyCatalog.GetBodyPrefabBodyComponent(bodyIndex); + if (bodyPrefabBodyComponent3.bodyColor != Color.clear) + { + return bodyPrefabBodyComponent3.bodyColor; + } + string bodyName = BodyCatalog.GetBodyName(bodyIndex); + ulong num3 = 0uL; + for (int j = 0; j < bodyName.Length; j++) + { + num3 += bodyName[j]; + } + Xoroshiro128Plus xoroshiro128Plus = new Xoroshiro128Plus(num3); + return Color.HSVToRGB(xoroshiro128Plus.nextNormalizedFloat, xoroshiro128Plus.RangeFloat(0.5f, 1f), xoroshiro128Plus.RangeFloat(0.6f, 0.8f)); + } + float GetStatWeight(StatDef statDef) + { + return statDef.dataType switch + { + StatDataType.ULong => statSheet.GetStatValueULong(statDef), + StatDataType.Double => (float)statSheet.GetStatValueDouble(statDef), + _ => throw new ArgumentOutOfRangeException(), + }; + } + void OnPageChangeSubmitted(int newPage) + { + callbacks[newPage](); + carousel.GetComponent().FindChild("StatLabel").GetComponent() + .text = statNames[newPage]; + } + void SetStats(RectTransform container, (string name, string value, Texture texture)[] data) + { + UIElementAllocator uIElementAllocator = new UIElementAllocator(container, statStripPrefab, markElementsUnsavable: true, acquireExistingChildren: true); + uIElementAllocator.AllocateElements(data.Length); + ReadOnlyCollection elements = uIElementAllocator.elements; + for (int i = 0; i < data.Length; i++) + { + (string name, string value, Texture texture) tuple2 = data[i]; + string item = tuple2.name; + string item2 = tuple2.value; + Texture item3 = tuple2.texture; + ChildLocator childLocator = elements[i]; + childLocator.FindChild("NameLabel").GetComponent().SetText(item); + childLocator.FindChild("ValueLabel").GetComponent().SetText("" + item2 + ""); + RawImage component2 = childLocator.FindChild("IconRawImage").GetComponent(); + component2.transform.parent.gameObject.SetActive(item3); + component2.texture = item3; + } + } + static (string name, string value, Texture2D texture) StatStripDataFromCompletionFraction(string displayToken, IntFraction completionFraction) + { + (string, string, Texture2D) result = default((string, string, Texture2D)); + result.Item1 = Language.GetString(displayToken); + result.Item2 = Language.GetStringFormatted("STAT_COMPLETION_VALUE_FORMAT", completionFraction.numerator, completionFraction.denominator, (float)completionFraction); + result.Item3 = null; + return result; + } + (string name, string value, Texture2D texture) StatStripDataFromStatDef(StatDef statDef) + { + (string, string, Texture2D) result2 = default((string, string, Texture2D)); + result2.Item1 = Language.GetString(statDef.displayToken); + result2.Item2 = statSheet.GetStatDisplayValue(statDef); + result2.Item3 = null; + return result2; + } + } + + public void AddRunReportPanel(RunReport runReport) + { + GameObject gameObject = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/UI/GameEndReportPanelScrolling"), container); + gameObject.GetComponent().SetDisplayData(new GameEndReportPanelController.DisplayData + { + runReport = runReport, + playerIndex = 0 + }); + gameObject.GetComponent().fallBackToMainEventSystem = true; + managedObjects.Add(gameObject); + } + + public static void RunReportPanel(PageBuilder builder) + { + builder.AddRunReportPanel((RunReport)builder.entry.extraData); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/BaseMainMenuScreen.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/BaseMainMenuScreen.cs new file mode 100644 index 0000000..18e5478 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/BaseMainMenuScreen.cs @@ -0,0 +1,64 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace RoR2.UI.MainMenu; + +[RequireComponent(typeof(RectTransform))] +public class BaseMainMenuScreen : MonoBehaviour +{ + public Transform desiredCameraTransform; + + [HideInInspector] + public bool shouldDisplay; + + protected MainMenuController myMainMenuController; + + protected FirstSelectedObjectProvider firstSelectedObjectProvider; + + public UnityEvent onEnter; + + public UnityEvent onExit; + + public void Awake() + { + firstSelectedObjectProvider = GetComponent(); + } + + public void OnEnable() + { + MainMenuController.instance?.SetAllowTransition(value: true); + } + + public virtual bool IsReadyToLeave() + { + return true; + } + + public void Update() + { + if (SimpleDialogBox.instancesList.Count == 0) + { + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + } + + public virtual void OnEnter(MainMenuController mainMenuController) + { + Debug.LogFormat("BaseMainMenuScreen: OnEnter()"); + myMainMenuController = mainMenuController; + if (SimpleDialogBox.instancesList.Count == 0) + { + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + onEnter.Invoke(); + } + + public virtual void OnExit(MainMenuController mainMenuController) + { + if (myMainMenuController == mainMenuController) + { + myMainMenuController = null; + } + onExit.Invoke(); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/LocalMultiplayerMenuController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/LocalMultiplayerMenuController.cs new file mode 100644 index 0000000..8d71cf6 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/LocalMultiplayerMenuController.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.UI.MainMenu; + +[RequireComponent(typeof(FirstSelectedObjectProvider))] +public class LocalMultiplayerMenuController : BaseMainMenuScreen +{ + public enum Subview + { + Main, + FindGame, + HostGame + } + + public enum MPButtons + { + HostGame, + FindGame, + Quickplay, + StartPrivateGame, + Invite, + FindFriendSession, + Back, + EnterGame, + NONE + } + + private const float titleTransitionDuration = 0.5f; + + private const float titleTransitionBuffer = 0.1f; + + public Image fadeImage; + + public LerpUIRect[] uiToLerp; + + private float titleStopwatch; + + private Subview _curSubView; + + [Header("Buttons")] + public MPButton backButton; + + public CarouselController gameModePicker; + + public MPButton enterGameButton; + + public static LocalMultiplayerMenuController instance { get; private set; } + + private void ToggleMPFeatures(MPFeatures featureFlags) + { + Toggle(gameModePicker, val: true); + Toggle(enterGameButton, val: true); + } + + private void ToggleMPFeaturesInteractable(MPFeatures featureFlags) + { + gameModePicker.ToggleArrowsInteractable(isInteractable: true); + if (enterGameButton != null) + { + enterGameButton.interactable = true; + } + } + + private void Toggle(MonoBehaviour component, bool val) + { + if ((bool)component) + { + component.gameObject.SetActive(val); + } + else + { + Debug.LogError("Null ref on Toggle of Button in MultiplayerMenuController on \"" + base.gameObject.name + "\""); + } + } + + private void Toggle(GameObject[] goToToggle, bool val) + { + int num = goToToggle.Length; + for (int i = 0; i < num; i++) + { + goToToggle[i].gameObject.SetActive(val); + } + } + + private void Toggle(MonoBehaviour[] buttons, bool val) + { + int num = buttons.Length; + for (int i = 0; i < num; i++) + { + buttons[i].gameObject.SetActive(val); + } + } + + public void SetButtonText(MPButton button, string textKey, object[] formatArgs = null) + { + if (formatArgs == null) + { + formatArgs = Array.Empty(); + } + TextMeshProUGUI component = button.GetComponent(); + if ((bool)component) + { + component.text = Language.GetStringFormatted(textKey, formatArgs); + } + } + + public void RefreshFirstObjectSelectedProvider() + { + if ((bool)firstSelectedObjectProvider) + { + firstSelectedObjectProvider.firstSelectedObject = gameModePicker.gameObject; + firstSelectedObjectProvider.fallBackFirstSelectedObjects = new GameObject[3] { gameModePicker.gameObject, enterGameButton.gameObject, backButton.gameObject }; + } + } + + public new void OnEnable() + { + RefreshFirstObjectSelectedProvider(); + firstSelectedObjectProvider?.ForceSelectFirstInteractable(); + LerpAllUI(LerpUIRect.LerpState.Entering); + if (!instance) + { + instance = SingletonHelper.Assign(instance, this); + } + firstSelectedObjectProvider?.ResetLastSelected(); + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + + public void OnDisable() + { + instance = SingletonHelper.Unassign(instance, this); + } + + public new void Awake() + { + base.Awake(); + LerpAllUI(LerpUIRect.LerpState.Entering); + BuildGameModeChoices(); + } + + public void LerpAllUI(LerpUIRect.LerpState lerpState) + { + LerpUIRect[] array = uiToLerp; + for (int i = 0; i < array.Length; i++) + { + array[i].lerpState = lerpState; + } + } + + private void BuildGameModeChoices() + { + List list = new List(); + List list2 = gameModePicker.choices.Select((CarouselController.Choice choice) => choice.suboptionDisplayToken).ToList(); + for (GameModeIndex gameModeIndex = (GameModeIndex)0; (int)gameModeIndex < GameModeCatalog.gameModeCount; gameModeIndex++) + { + Run gameModePrefabComponent = GameModeCatalog.GetGameModePrefabComponent(gameModeIndex); + ExpansionRequirementComponent component = gameModePrefabComponent.GetComponent(); + if (gameModePrefabComponent != null && gameModePrefabComponent.userPickable && list2.Contains(gameModePrefabComponent.nameToken) && (!component || !component.requiredExpansion || EntitlementManager.localUserEntitlementTracker.AnyUserHasEntitlement(component.requiredExpansion.requiredEntitlement))) + { + list.Add(new CarouselController.Choice + { + suboptionDisplayToken = gameModePrefabComponent.nameToken, + convarValue = gameModePrefabComponent.name + }); + } + } + gameModePicker.choices = list.ToArray(); + gameModePicker.gameObject.SetActive(list.Count > 0); + string @string = Console.instance.FindConVar("gamemode").GetString(); + bool flag = false; + for (int i = 0; i < list.Count; i++) + { + if (list[i].convarValue == @string) + { + flag = true; + break; + } + } + if (list.Count == 1 || !flag) + { + Debug.LogFormat("Invalid gamemode {0} detected. Reverting to ClassicRun.", @string); + gameModePicker.SubmitSetting(list[0].convarValue); + } + } + + public void ReturnToMainMenu() + { + myMainMenuController.SetDesiredMenuScreen(myMainMenuController.titleMenuScreen); + } + + public void OnEnterGameButtonPressed() + { + titleStopwatch = 0f; + LerpAllUI(LerpUIRect.LerpState.Leaving); + } + + public void OnStartGamePressed() + { + string @string = Console.instance.FindConVar("gamemode").GetString(); + Console.instance.SubmitCmd(null, $"transition_command \"gamemode {@string}; host 0;\""); + } + + private new void Update() + { + base.Update(); + titleStopwatch += Time.deltaTime; + if (enterGameButton != null && enterGameButton.isActiveAndEnabled) + { + enterGameButton.interactable = true; + } + if (SimpleDialogBox.instancesList.Count > 0 && (bool)firstSelectedObjectProvider) + { + SimpleDialogBox simpleDialogBox = SimpleDialogBox.instancesList[0]; + if ((bool)simpleDialogBox) + { + firstSelectedObjectProvider.firstSelectedObject = simpleDialogBox.GetComponentInChildren().gameObject; + firstSelectedObjectProvider.ResetLastSelected(); + } + } + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + + public override bool IsReadyToLeave() + { + return true; + } + + public void GoBack() + { + ReturnToMainMenu(); + } + + public void ResetLastSelected() + { + firstSelectedObjectProvider?.ResetLastSelected(); + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + + public void ToggleAllButtonsInteractable(bool interactable) + { + for (int i = 0; i < 8; i++) + { + SetButtonInteractableStatus((MPButtons)i, interactable); + } + firstSelectedObjectProvider.ForceSelectFirstInteractable(); + } + + public void SetButtonInteractableStatus(MPButtons button, bool interactable) + { + MPButton mPButton = null; + switch (button) + { + case MPButtons.Back: + mPButton = backButton; + break; + case MPButtons.EnterGame: + mPButton = enterGameButton; + break; + } + if (mPButton != null) + { + mPButton.interactable = interactable; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/MainMenuController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/MainMenuController.cs new file mode 100644 index 0000000..52bc9a1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/MainMenuController.cs @@ -0,0 +1,530 @@ +using System; +using System.Collections; +using Assets.RoR2.Scripts.Platform; +using RoR2.ConVar; +using RoR2.Networking; +using RoR2.UI.LogBook; +using UnityEngine; +using UnityEngine.Networking; + +namespace RoR2.UI.MainMenu; + +public sealed class MainMenuController : MonoBehaviour +{ + [NonSerialized] + public BaseMainMenuScreen desiredMenuScreen; + + public BaseMainMenuScreen LoadingScreen; + + public BaseMainMenuScreen profileMenuScreen; + + public BaseMainMenuScreen EAwarningProfileMenu; + + public BaseMainMenuScreen multiplayerMenuScreen; + + public BaseMainMenuScreen localMultiplayerMenuScreen; + + public BaseMainMenuScreen titleMenuScreen; + + public BaseMainMenuScreen settingsMenuScreen; + + public BaseMainMenuScreen moreMenuScreen; + + public BaseMainMenuScreen extraGameModeMenuScreen; + + [HideInInspector] + public BaseMainMenuScreen currentMenuScreen; + + public static MainMenuController instance; + + public HGButton exitButtonTransition; + + public HGButton profileButtonTransition; + + public HGButton onlineMultiplayerButtonTransition; + + public HGButton localMultiplayerButtonTransition; + + public HGButton splitscreenMultiplayerButtonTransition; + + public HGButton logbookButton; + + public HGButton singlePlayerButton; + + public GameObject steamBuildLabel; + + [NonSerialized] + public bool allowTransition = true; + + public HGButton continueButtonTransition; + + public GameObject EA_Panel; + + public GameObject mainMenuButtonPanel; + + public Transform cameraTransform; + + public float camRotationSmoothDampTime; + + public float camTranslationSmoothDampTime; + + private Vector3 camSmoothDampPositionVelocity; + + private Vector3 camSmoothDampRotationVelocity; + + public float camTransitionDuration; + + private float camTransitionTimer; + + private static bool isShownAgeRestriction = false; + + private static bool wasInMultiplayer = false; + + private static EOSLoginManager.EOSLoginState lastEOSLoginState = EOSLoginManager.EOSLoginState.None; + + private static bool eaWarningShown = false; + + private static BoolConVar eaMessageSkipConVar = new BoolConVar("ea_message_skip", ConVarFlags.None, "0", "Whether or not to skip the early access splash screen."); + + private static bool _isInitialized = false; + + public static bool IsOnMultiplayerScreen { get; set; } = false; + + + private static bool isInitialized + { + get + { + return _isInitialized; + } + set + { + _isInitialized = value; + if (_isInitialized) + { + MainMenuController.OnMainMenuInitialised?.Invoke(); + } + } + } + + public static event Action OnMainMenuInitialised; + + public static event Action OnPreMainMenuInitialized; + + [SystemInitializer(new Type[] { })] + private static void Init() + { + NetworkManagerSystem.onStartClientGlobal += delegate + { + if (!NetworkServer.active || !NetworkServer.dontListen) + { + wasInMultiplayer = true; + } + }; + } + + private void Awake() + { + RoR2Application.onStart = (Action)Delegate.Combine(RoR2Application.onStart, new Action(StartManaged)); + PauseManager.InitializeLoad(); + RoR2Application.isInLocalMultiPlayer = false; + } + + private void OnDestroy() + { + } + + public void SetButtonsInteractible(bool enabled) + { + exitButtonTransition.interactable = enabled; + profileButtonTransition.interactable = enabled; + onlineMultiplayerButtonTransition.interactable = enabled; + localMultiplayerButtonTransition.interactable = enabled; + splitscreenMultiplayerButtonTransition.interactable = enabled; + logbookButton.interactable = enabled; + } + + private void OnNetworkReachabilityChanged(bool networkReachability) + { + if (networkReachability) + { + SetupMPFeatureButtons(); + } + } + + private void Start() + { + if (instance != null) + { + UnityEngine.Object.Destroy(base.gameObject); + return; + } + instance = this; + SetupMPFeatureButtons(); + exitButtonTransition.transform.SetAsLastSibling(); + StartWaitForLoad(); + if ((bool)LoadingScreen) + { + LoadingScreen.gameObject.SetActive(value: true); + } + titleMenuScreen.gameObject.SetActive(value: false); + multiplayerMenuScreen.gameObject.SetActive(value: false); + localMultiplayerMenuScreen.gameObject.SetActive(value: false); + settingsMenuScreen.gameObject.SetActive(value: false); + moreMenuScreen.gameObject.SetActive(value: false); + extraGameModeMenuScreen.gameObject.SetActive(value: false); + if (GameIntentReceiver.GameIntentAdapter.hasPendingGameIntent) + { + FadeToBlackManager.fadePaused = true; + } + desiredMenuScreen = (wasInMultiplayer ? multiplayerMenuScreen : titleMenuScreen); + _ = wasInMultiplayer; + wasInMultiplayer = false; + StartManaged(); + } + + private void DisableButtonsForConsole() + { + } + + private void SetupMPFeatureButtons() + { + bool flag = PlatformSystems.lobbyManager.GetPlatformMPFeatureFlags().HasFlag(MPFeatures.AdHoc); + localMultiplayerButtonTransition.gameObject.SetActive(flag); + LanguageTextMeshController componentInChildren = onlineMultiplayerButtonTransition.GetComponentInChildren(); + if ((bool)componentInChildren) + { + componentInChildren.token = (flag ? "TITLE_MULTIPLAYER_ONLINE" : "TITLE_MULTIPLAYER"); + } + splitscreenMultiplayerButtonTransition.gameObject.SetActive(value: false); + } + + private void DialogBox(string headerToken, string descriptionToken) + { + if (SimpleDialogBox.instancesList.Count == 0) + { + SimpleDialogBox simpleDialogBox = SimpleDialogBox.Create(); + simpleDialogBox.headerToken = new SimpleDialogBox.TokenParamsPair(headerToken); + simpleDialogBox.descriptionToken = new SimpleDialogBox.TokenParamsPair(descriptionToken); + simpleDialogBox.AddCancelButton(CommonLanguageTokens.ok); + simpleDialogBox.rootObject.transform.SetParent(RoR2Application.instance.mainCanvas.transform); + } + } + + private void StartManaged() + { + CheckWarningScreen(); + currentMenuScreen = desiredMenuScreen; + if (!currentMenuScreen.gameObject.activeInHierarchy) + { + currentMenuScreen.gameObject.SetActive(value: true); + } + if (currentMenuScreen.desiredCameraTransform != null) + { + cameraTransform.rotation = currentMenuScreen.desiredCameraTransform.rotation; + } + if ((bool)currentMenuScreen) + { + currentMenuScreen.OnEnter(this); + } + IsOnMultiplayerScreen = currentMenuScreen == multiplayerMenuScreen; + } + + private bool CheckWarningScreen() + { + return false; + } + + private static bool IsMainUserSignedIn() + { + return LocalUserManager.FindLocalUser(0) != null; + } + + private bool IsInLobby() + { + return PlatformSystems.lobbyManager.isInLobby; + } + + private void Update() + { + if (isInitialized) + { + if (currentMenuScreen == multiplayerMenuScreen && PlayerPrefs.GetInt("HasShownFirstTimePopup", 0) == 0) + { + PlayerPrefs.SetInt("HasShownFirstTimePopup", 1); + ShowFirstTimeCrossPlayPopup(); + } + if (IsInLobby() && currentMenuScreen != multiplayerMenuScreen && currentMenuScreen != localMultiplayerMenuScreen) + { + desiredMenuScreen = multiplayerMenuScreen; + } + if (!IsMainUserSignedIn() && currentMenuScreen != EAwarningProfileMenu) + { + desiredMenuScreen = profileMenuScreen; + } + if (!(currentMenuScreen == null)) + { + UpdateMenuTransition(); + } + } + } + + private void UpdateMenuTransition() + { + if (desiredMenuScreen != currentMenuScreen) + { + if (desiredMenuScreen == multiplayerMenuScreen && PlatformSystems.userManager.CurrentUserHasRestriction(UserManager.PlatformRestriction.Multiplayer)) + { + PlatformSystems.userManager.DisplayRestrictionMessage(); + desiredMenuScreen = currentMenuScreen; + return; + } + currentMenuScreen.shouldDisplay = false; + if (currentMenuScreen.IsReadyToLeave()) + { + MPEventSystemLocator component = GetComponent(); + if ((bool)component) + { + component.eventSystem.SetSelectedObject(null); + } + if (currentMenuScreen == multiplayerMenuScreen && desiredMenuScreen == titleMenuScreen) + { + MultiplayerMenuController.instance?.ResetLobby(); + } + currentMenuScreen.OnExit(this); + currentMenuScreen.gameObject.SetActive(value: false); + currentMenuScreen = desiredMenuScreen; + camTransitionTimer = camTransitionDuration; + currentMenuScreen.OnEnter(this); + IsOnMultiplayerScreen = currentMenuScreen == multiplayerMenuScreen; + } + } + else if (currentMenuScreen.desiredCameraTransform != null) + { + camTransitionTimer -= Time.deltaTime; + cameraTransform.position = Vector3.SmoothDamp(cameraTransform.position, currentMenuScreen.desiredCameraTransform.position, ref camSmoothDampPositionVelocity, camTranslationSmoothDampTime); + Vector3 eulerAngles = cameraTransform.eulerAngles; + Vector3 eulerAngles2 = currentMenuScreen.desiredCameraTransform.eulerAngles; + eulerAngles.x = Mathf.SmoothDampAngle(eulerAngles.x, eulerAngles2.x, ref camSmoothDampRotationVelocity.x, camRotationSmoothDampTime, float.PositiveInfinity, Time.unscaledDeltaTime); + eulerAngles.y = Mathf.SmoothDampAngle(eulerAngles.y, eulerAngles2.y, ref camSmoothDampRotationVelocity.y, camRotationSmoothDampTime, float.PositiveInfinity, Time.unscaledDeltaTime); + eulerAngles.z = Mathf.SmoothDampAngle(eulerAngles.z, eulerAngles2.z, ref camSmoothDampRotationVelocity.z, camRotationSmoothDampTime, float.PositiveInfinity, Time.unscaledDeltaTime); + cameraTransform.eulerAngles = eulerAngles; + if (camTransitionTimer <= 0f) + { + currentMenuScreen.gameObject.SetActive(value: true); + currentMenuScreen.shouldDisplay = true; + } + } + } + + public void SetAllowTransition(bool value) + { + allowTransition = value; + } + + public void SetDesiredMenuScreen(BaseMainMenuScreen newDesiredMenuScreen) + { + if (allowTransition) + { + desiredMenuScreen = newDesiredMenuScreen; + } + } + + public void ClearEngagementScreen() + { + if (!CheckWarningScreen()) + { + desiredMenuScreen = titleMenuScreen; + } + } + + private void UpdateEoSLoginState() + { + if (lastEOSLoginState == EOSLoginManager.loginState) + { + return; + } + switch (EOSLoginManager.loginState) + { + case EOSLoginManager.EOSLoginState.AttemptingLink: + AddAccountLinkPopup(); + break; + case EOSLoginManager.EOSLoginState.FailedLogin: + AddAccountLinkPopup(); + break; + case EOSLoginManager.EOSLoginState.FailedLink: + AddAccountLinkPopup(); + break; + case EOSLoginManager.EOSLoginState.Success: + if (titleMenuScreen.isActiveAndEnabled) + { + mainMenuButtonPanel?.SetActive(value: true); + } + break; + } + lastEOSLoginState = EOSLoginManager.loginState; + } + + private void AddAccountLinkPopup() + { + SimpleDialogBox dialogBox = SimpleDialogBox.Create(); + Action retryLoginFunction = delegate + { + if ((bool)dialogBox) + { + RetryLogin(); + } + }; + Action deactiveCrossplayAndRestartFunction = delegate + { + if ((bool)dialogBox) + { + DeactiveCrossPlayAndRestart(); + } + }; + dialogBox.headerToken = new SimpleDialogBox.TokenParamsPair + { + token = "EOS_NOT_LINKED_TITLE", + formatParams = Array.Empty() + }; + dialogBox.descriptionToken = new SimpleDialogBox.TokenParamsPair + { + token = "EOS_NOT_LINKED_MESSAGE", + formatParams = Array.Empty() + }; + dialogBox.AddActionButton(delegate + { + retryLoginFunction(); + }, "EOS_RETRY_LOGIN", true); + dialogBox.AddActionButton(delegate + { + deactiveCrossplayAndRestartFunction(); + }, "EOS_DEACTIVATE_CROSSPLAY_RESTART", true); + } + + private void RetryLogin() + { + if (EOSLoginManager.loggedInAuthId == null) + { + new EOSLoginManager().TryLogin(); + } + else if (titleMenuScreen.isActiveAndEnabled) + { + mainMenuButtonPanel?.SetActive(value: true); + } + } + + private void DeactiveCrossPlayAndRestart() + { + Console.instance.FindConVar("egsToggle")?.AttemptSetString("0"); + Console.instance.SubmitCmd(null, "quit"); + } + + private void ShowFirstTimeCrossPlayPopup() + { + SimpleDialogBox dialogBox = SimpleDialogBox.Create(); + Action activateCrossplayFunction = delegate + { + if ((bool)dialogBox) + { + ActivateCrossPlay(); + } + }; + Action deactivateCrossplayFunction = delegate + { + if ((bool)dialogBox) + { + DeactivateCrossPlay(); + } + }; + Action ShowCrossplayInfo = delegate + { + if ((bool)dialogBox) + { + Application.OpenURL("https://support.gearboxsoftware.com/hc/en-us/articles/4440999200269"); + } + }; + dialogBox.headerToken = new SimpleDialogBox.TokenParamsPair + { + token = "FIRST_TIME_CROSSPLAY_POPUP_HEADER", + formatParams = Array.Empty() + }; + dialogBox.descriptionToken = new SimpleDialogBox.TokenParamsPair + { + token = "FIRST_TIME_CROSSPLAY_POPUP_DESCRIPTION", + formatParams = Array.Empty() + }; + dialogBox.AddActionButton(delegate + { + activateCrossplayFunction(); + }, "STAT_CONTINUE", true); + dialogBox.AddActionButton(delegate + { + ShowCrossplayInfo(); + }, "FIRST_TIME_CROSSPLAY_POPUP_INFO", false); + dialogBox.AddActionButton(delegate + { + deactivateCrossplayFunction(); + }, "FIRST_TIME_CROSSPLAY_POPUP_DISABLE_CROSSPLAY", true); + static void ActivateCrossPlay() + { + PlayerPrefs.SetInt("ShownFirstTimePopup", 1); + } + static void DeactivateCrossPlay() + { + PlayerPrefs.SetInt("ShownFirstTimePopup", 1); + Console.instance.FindConVar("egsToggle")?.AttemptSetString("1"); + Console.instance.SubmitCmd(null, "quit"); + } + } + + public void StartWaitForLoad() + { + if (!IsMainUserSignedIn()) + { + StartCoroutine(WaitForPlatformLoad()); + return; + } + MainMenuController.OnPreMainMenuInitialized?.Invoke(); + isInitialized = true; + } + + private IEnumerator WaitForPlatformLoad() + { + MainMenuController.OnPreMainMenuInitialized?.Invoke(); + SaveSystem platformSaveSystem = PlatformSystems.saveSystem; + platformSaveSystem.LoadInitialData(); + while (!platformSaveSystem.isInitialLoadFinished) + { + yield return null; + } + PlatformSystems.userManager.EnableUserControllerHandling(); + if (platformSaveSystem.userProfile != null) + { + LocalUserManager.SetLocalUsers(new LocalUserManager.LocalUserInitializationInfo[1] + { + new LocalUserManager.LocalUserInitializationInfo + { + profile = platformSaveSystem.userProfile + } + }); + Console.instance.SubmitCmd(null, "exec config"); + logbookButton.interactable = false; + while (!LogBookController.IsStaticDataReady) + { + yield return null; + } + logbookButton.interactable = true; + isInitialized = true; + } + else + { + isInitialized = true; + } + } + + public void EnableContinueEAWarningButton() + { + continueButtonTransition.interactable = true; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/MultiplayerMenuController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/MultiplayerMenuController.cs new file mode 100644 index 0000000..966f57c --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/MultiplayerMenuController.cs @@ -0,0 +1,730 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using RoR2.EntitlementManagement; +using RoR2.ExpansionManagement; +using RoR2.Networking; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.UI.MainMenu; + +[RequireComponent(typeof(FirstSelectedObjectProvider))] +public class MultiplayerMenuController : BaseMainMenuScreen +{ + public enum Subview + { + Main, + FindGame, + HostGame + } + + public enum MPButtons + { + HostGame, + FindGame, + Quickplay, + StartPrivateGame, + Invite, + FindFriendSession, + Back, + EnterGame, + NONE + } + + private const float titleTransitionDuration = 0.5f; + + private const float titleTransitionBuffer = 0.1f; + + public Image fadeImage; + + public LerpUIRect[] uiToLerp; + + private float titleStopwatch; + + private Subview _curSubView; + + [Header("Subviews")] + public GameObject MainMultiplayerMenu; + + public GameObject JoinGameMenu; + + public GameObject HostGameMenu; + + [Header("Buttons")] + public MPButton hostGame; + + public MPButton findGame; + + public MPButton quickplayButton; + + public MPButton startPrivateGameButton; + + public MPButton inviteButton; + + public MPButton findFriendSessionButton; + + public MPButton backButton; + + public CarouselController gameModePicker; + + public MPButton enterGameButton; + + public GameObject[] lobbyActions; + + [Header("Quickplay Logic")] + public LanguageTextMeshController quickplayLabelController; + + public string quickplayStartToken; + + public string quickplayStopToken; + + public RectTransform quickplaySpinnerRectTransform; + + public TextMeshProUGUI quickplayStateText; + + private string pendingQuickplayText; + + public RectTransform genericSpinnerRectTransform; + + private const float spinnerRotationSpeed = 360f; + + [Header("Sub-Views")] + public SteamJoinClipboardLobby joinClipboardLobbyButtonController; + + public FriendSessionBrowserController friendSessionBrowserController; + + public LobbyUserList lobbyUserList; + + [Header("Platform Specific Components")] + public CarouselController lobbyVisibilityController; + + public static float QuickplayWaitTime; + + public bool IsQuickPlaySearching; + + public bool IsQuickPlayButtonLocked; + + private Coroutine checkCanPlayOnlineCoroutine; + + public static MultiplayerMenuController instance { get; private set; } + + public Subview GetCurrentSubview() + { + return _curSubView; + } + + public void SetSubview(Subview targetSubview) + { + _curSubView = targetSubview; + MainMultiplayerMenu.SetActive(targetSubview == Subview.Main); + JoinGameMenu.SetActive(targetSubview == Subview.FindGame); + HostGameMenu.SetActive(targetSubview == Subview.HostGame); + if ((bool)lobbyUserList) + { + lobbyUserList.DisplayContent(targetSubview == Subview.HostGame || targetSubview == Subview.Main); + } + } + + public void ReturnToMainSubview() + { + SetSubview(Subview.Main); + } + + private void ToggleMPFeatures(MPFeatures featureFlags) + { + Toggle(hostGame, featureFlags.HasFlag(MPFeatures.HostGame)); + Toggle(findGame, featureFlags.HasFlag(MPFeatures.FindGame)); + Toggle(quickplayButton, featureFlags.HasFlag(MPFeatures.Quickplay)); + Toggle(gameModePicker, val: true); + Toggle(startPrivateGameButton, featureFlags.HasFlag(MPFeatures.PrivateGame)); + Toggle(inviteButton, featureFlags.HasFlag(MPFeatures.Invite)); + Toggle(findFriendSessionButton, featureFlags.HasFlag(MPFeatures.FindFriendSession)); + Toggle(enterGameButton, featureFlags.HasFlag(MPFeatures.EnterGameButton)); + } + + private void ToggleMPFeaturesInteractable(MPFeatures featureFlags) + { + hostGame.interactable = featureFlags.HasFlag(MPFeatures.HostGame); + findGame.interactable = featureFlags.HasFlag(MPFeatures.FindGame); + quickplayButton.interactable = featureFlags.HasFlag(MPFeatures.Quickplay) && ShouldEnableQuickplayButton(); + gameModePicker.ToggleArrowsInteractable(isInteractable: true); + startPrivateGameButton.interactable = featureFlags.HasFlag(MPFeatures.PrivateGame); + inviteButton.interactable = featureFlags.HasFlag(MPFeatures.Invite); + findFriendSessionButton.interactable = featureFlags.HasFlag(MPFeatures.FindFriendSession); + if (enterGameButton != null) + { + enterGameButton.interactable = PlatformSystems.lobbyManager.ShouldEnableEnterGameButton(); + } + } + + private void SetDefaultFallback() + { + if (quickplayButton.isActiveAndEnabled) + { + quickplayButton.defaultFallbackButton = true; + } + } + + private void ToggleMPLobbyFeaturesInteractable(MPLobbyFeatures lobbyFlags) + { + lobbyUserList.createLobbyButton.interactable = lobbyFlags.HasFlag(MPLobbyFeatures.CreateLobby); + lobbyUserList.leaveLobbyButton.interactable = lobbyFlags.HasFlag(MPLobbyFeatures.LeaveLobby); + lobbyUserList.copyLobbyButton.interactable = lobbyFlags.HasFlag(MPLobbyFeatures.Clipboard); + lobbyUserList.joinLobbyButton.interactable = lobbyFlags.HasFlag(MPLobbyFeatures.Clipboard); + lobbyUserList.lobbyTypeDropdown.interactable = lobbyFlags.HasFlag(MPLobbyFeatures.LobbyDropdownOptions); + } + + private void Toggle(MonoBehaviour component, bool val) + { + if ((bool)component) + { + component.gameObject.SetActive(val); + } + else + { + Debug.LogError("Null ref on Toggle of Button in MultiplayerMenuController on \"" + base.gameObject.name + "\""); + } + } + + private void Toggle(GameObject[] goToToggle, bool val) + { + int num = goToToggle.Length; + for (int i = 0; i < num; i++) + { + goToToggle[i].gameObject.SetActive(val); + } + } + + private void Toggle(MonoBehaviour[] buttons, bool val) + { + int num = buttons.Length; + for (int i = 0; i < num; i++) + { + buttons[i].gameObject.SetActive(val); + } + } + + public void SetQuickplayButtonStateText(string textKey, object[] formatArgs = null) + { + if (formatArgs == null) + { + formatArgs = Array.Empty(); + } + TextMeshProUGUI textMeshProUGUI = quickplayStateText; + if ((bool)textMeshProUGUI) + { + textMeshProUGUI.text = Language.GetStringFormatted(textKey, formatArgs); + } + } + + public void SetButtonText(MPButton button, string textKey, object[] formatArgs = null) + { + if (formatArgs == null) + { + formatArgs = Array.Empty(); + } + TextMeshProUGUI component = button.GetComponent(); + if ((bool)component) + { + component.text = Language.GetStringFormatted(textKey, formatArgs); + } + } + + public void SetNetworkType(bool isInternet) + { + PlatformSystems.lobbyManager.SetNetworkType(isInternet); + } + + public void RefreshFirstObjectSelectedProvider() + { + if ((bool)firstSelectedObjectProvider) + { + firstSelectedObjectProvider.firstSelectedObject = gameModePicker.gameObject; + firstSelectedObjectProvider.fallBackFirstSelectedObjects = new GameObject[9] { gameModePicker.gameObject, hostGame.gameObject, findGame.gameObject, quickplayButton.gameObject, enterGameButton.gameObject, startPrivateGameButton.gameObject, inviteButton.gameObject, findFriendSessionButton.gameObject, backButton.gameObject }; + } + } + + public new void OnEnable() + { + ResetText(); + ToggleMPFeatures(PlatformSystems.lobbyManager.GetPlatformMPFeatureFlags()); + SetupLocalAndInternetMPButtons(); + if ((bool)lobbyUserList) + { + lobbyUserList.DisplayContent(display: true); + } + RefreshFirstObjectSelectedProvider(); + BuildGameModeChoices(); + SetDefaultFallback(); + firstSelectedObjectProvider?.ForceSelectFirstInteractable(); + LerpAllUI(LerpUIRect.LerpState.Entering); + if (!instance) + { + instance = SingletonHelper.Assign(instance, this); + } + PlatformSystems.lobbyManager.OnMultiplayerMenuEnabled(OnLobbyLeave); + checkCanPlayOnlineCoroutine = StartCoroutine(CheckCanPlayOnline()); + firstSelectedObjectProvider?.ResetLastSelected(); + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + + private IEnumerator CheckCanPlayOnline() + { + IEnumerator canPlayOnlineEnumerator = NetworkManagerSystem.singleton.CanPlayOnline(); + NetworkManagerSystem.CanPlayOnlineState lastResult = NetworkManagerSystem.CanPlayOnlineState.Pending; + while (canPlayOnlineEnumerator.MoveNext()) + { + lastResult = canPlayOnlineEnumerator.Current; + if (lastResult != 0) + { + break; + } + yield return null; + } + if (lastResult != NetworkManagerSystem.CanPlayOnlineState.Yes) + { + if (!NetworkManagerSystem.singleton.isNetworkActive) + { + PlatformSystems.lobbyManager.LeaveLobby(); + } + myMainMenuController.SetDesiredMenuScreen(myMainMenuController.titleMenuScreen); + } + checkCanPlayOnlineCoroutine = null; + } + + public void OnDisable() + { + if (checkCanPlayOnlineCoroutine != null) + { + StopCoroutine(checkCanPlayOnlineCoroutine); + } + LobbyManager lobbyManager = PlatformSystems.lobbyManager; + lobbyManager.onLobbyLeave = (Action)Delegate.Remove(lobbyManager.onLobbyLeave, new Action(OnLobbyLeave)); + if (!NetworkManagerSystem.singleton.isNetworkActive) + { + PlatformSystems.lobbyManager.LeaveLobby(); + } + instance = SingletonHelper.Unassign(instance, this); + } + + private void OnLobbyLeave(PlatformID lobbyId) + { + ResetText(); + if (!(PlatformSystems.lobbyManager as SteamworksLobbyManager).isInLobbyDelayed && !PlatformSystems.lobbyManager.awaitingJoin && MainMenuController.instance.desiredMenuScreen == MainMenuController.instance.multiplayerMenuScreen) + { + PlatformSystems.lobbyManager.CreateLobby(); + } + } + + public new void Awake() + { + base.Awake(); + LerpAllUI(LerpUIRect.LerpState.Entering); + hostGame.onClick.AddListener(delegate + { + SetSubview(Subview.HostGame); + }); + findGame.onClick.AddListener(delegate + { + SetSubview(Subview.FindGame); + }); + quickplayButton.onClick.AddListener(delegate + { + PlatformSystems.lobbyManager.ToggleQuickplay(); + }); + startPrivateGameButton.onClick.AddListener(delegate + { + PlatformSystems.lobbyManager.OnStartPrivateGame(); + }); + findFriendSessionButton.onClick.AddListener(delegate + { + PlatformSystems.lobbyManager.OpenFriendSessionBrowser(); + }); + } + + public void ShowFriendSessionBrowser() + { + friendSessionBrowserController.gameObject.SetActive(value: true); + } + + public void LerpAllUI(LerpUIRect.LerpState lerpState) + { + LerpUIRect[] array = uiToLerp; + for (int i = 0; i < array.Length; i++) + { + array[i].lerpState = lerpState; + } + } + + private void BuildGameModeChoices() + { + List list = new List(); + List list2 = gameModePicker.choices.Select((CarouselController.Choice choice) => choice.suboptionDisplayToken).ToList(); + for (GameModeIndex gameModeIndex = (GameModeIndex)0; (int)gameModeIndex < GameModeCatalog.gameModeCount; gameModeIndex++) + { + Run gameModePrefabComponent = GameModeCatalog.GetGameModePrefabComponent(gameModeIndex); + ExpansionRequirementComponent component = gameModePrefabComponent.GetComponent(); + if (gameModePrefabComponent != null && gameModePrefabComponent.userPickable && list2.Contains(gameModePrefabComponent.nameToken) && (!component || !component.requiredExpansion || EntitlementManager.localUserEntitlementTracker.AnyUserHasEntitlement(component.requiredExpansion.requiredEntitlement))) + { + list.Add(new CarouselController.Choice + { + suboptionDisplayToken = gameModePrefabComponent.nameToken, + convarValue = gameModePrefabComponent.name + }); + } + } + gameModePicker.choices = list.ToArray(); + gameModePicker.gameObject.SetActive(list.Count > 1); + string @string = Console.instance.FindConVar("gamemode").GetString(); + bool flag = false; + for (int i = 0; i < list.Count; i++) + { + if (list[i].convarValue == @string) + { + flag = true; + break; + } + } + if (list.Count == 1 || !flag) + { + Debug.LogFormat("Invalid gamemode {0} detected. Reverting to ClassicRun.", @string); + gameModePicker.SubmitSetting(list[0].convarValue); + } + } + + public void ResetText() + { + if (PlatformSystems.lobbyManager.GetPlatformMPFeatureFlags().HasFlag(MPFeatures.Quickplay)) + { + SetQuickplayText("", new object[0]); + } + } + + private void SetupLocalAndInternetMPButtons() + { + LanguageTextMeshController componentInChildren = findFriendSessionButton.GetComponentInChildren(); + LanguageTextMeshController languageTextMeshController = (inviteButton as HGButton)?.hoverLanguageTextMeshController; + LanguageTextMeshController componentInChildren2 = startPrivateGameButton.GetComponentInChildren(); + if (PlatformSystems.lobbyManager.IsNetworkTypeInternet()) + { + if ((bool)componentInChildren) + { + componentInChildren.token = "FRIEND_GAME_BROWSER"; + } + if ((bool)languageTextMeshController) + { + languageTextMeshController.token = "FRIEND_GAME_BROWSER_DESCRIPTION"; + } + if ((bool)componentInChildren2) + { + componentInChildren2.token = "HOST_PRIVATE_GAME"; + } + return; + } + enterGameButton.interactable = false; + if ((bool)componentInChildren) + { + componentInChildren.token = "BROWSE_LOCAL_GAME"; + } + if ((bool)languageTextMeshController) + { + languageTextMeshController.token = "BROWSE_LOCAL_GAME_DESCRIPTION"; + } + if ((bool)componentInChildren2) + { + componentInChildren2.token = "HOST_LOCAL_GAME"; + } + } + + public void ReturnToMainMenu() + { + ResetLobby(); + myMainMenuController.SetDesiredMenuScreen(myMainMenuController.titleMenuScreen); + } + + public void ResetLobby() + { + PlatformSystems.lobbyManager.LeaveLobby(); + if (enterGameButton != null) + { + enterGameButton.interactable = PlatformSystems.lobbyManager.ShouldEnableEnterGameButton(); + } + lobbyUserList.ClearUserList(); + } + + public void OnEnterGameButtonPressed() + { + titleStopwatch = 0f; + LerpAllUI(LerpUIRect.LerpState.Leaving); + PlatformSystems.lobbyManager.EnterGameButtonPressed(); + } + + private void UpdateSpinner(RectTransform spinnerRectTransform) + { + Vector3 localEulerAngles = spinnerRectTransform.localEulerAngles; + localEulerAngles.z += Time.deltaTime * 360f; + spinnerRectTransform.localEulerAngles = localEulerAngles; + } + + private new void Update() + { + base.Update(); + titleStopwatch += Time.deltaTime; + PlatformSystems.lobbyManager.CheckBusyTimer(); + if (friendSessionBrowserController.gameObject.activeSelf) + { + return; + } + if (PlatformSystems.lobbyManager.IsQuickPlaySearching()) + { + ToggleMPFeaturesInteractable(MPFeatures.Quickplay); + quickplayLabelController.token = quickplayStopToken; + } + if (PlatformSystems.lobbyManager.ShouldShowSpinner()) + { + quickplaySpinnerRectTransform.gameObject.SetActive(value: true); + UpdateSpinner(quickplaySpinnerRectTransform); + } + else + { + ToggleMPFeaturesInteractable(PlatformSystems.lobbyManager.GetPlatformMPFeatureFlags()); + quickplaySpinnerRectTransform.gameObject.SetActive(value: false); + if (!PlatformSystems.lobbyManager.IsQuickPlaySearching()) + { + quickplayLabelController.token = quickplayStartToken; + } + else + { + quickplayLabelController.token = quickplayStopToken; + } + if ((bool)quickplayButton) + { + quickplayButton.interactable = ShouldEnableQuickplayButton(); + } + else + { + quickplayButton.interactable = ShouldEnableQuickplayButton(); + if (!ShouldEnableQuickplayButton()) + { + quickplaySpinnerRectTransform.gameObject.SetActive(value: true); + UpdateSpinner(quickplaySpinnerRectTransform); + } + } + if ((bool)startPrivateGameButton) + { + startPrivateGameButton.interactable = ShouldEnableStartPrivateGameButton(); + } + if ((bool)joinClipboardLobbyButtonController && (bool)joinClipboardLobbyButtonController.mpButton) + { + joinClipboardLobbyButtonController.mpButton.interactable = ShouldEnableJoinClipboardLobbyButton(); + } + if ((bool)inviteButton) + { + inviteButton.interactable = PlatformSystems.lobbyManager.ShouldEnableInviteButton(); + } + if ((bool)findFriendSessionButton) + { + findFriendSessionButton.interactable = ShouldEnableFindFriendSessionButton(); + } + backButton.interactable = ShouldEnableBackButton(); + if (enterGameButton != null && enterGameButton.isActiveAndEnabled) + { + enterGameButton.interactable = PlatformSystems.lobbyManager.ShouldEnableEnterGameButton(); + } + } + if (PlatformSystems.lobbyManager.ShouldShowGenericSpinner()) + { + genericSpinnerRectTransform.gameObject.SetActive(value: true); + UpdateSpinner(genericSpinnerRectTransform); + } + else + { + genericSpinnerRectTransform.gameObject.SetActive(value: false); + } + if (!string.IsNullOrEmpty(pendingQuickplayText)) + { + SetQuickplayText(pendingQuickplayText); + pendingQuickplayText = string.Empty; + } + if (SimpleDialogBox.instancesList.Count > 0 && (bool)firstSelectedObjectProvider) + { + SimpleDialogBox simpleDialogBox = SimpleDialogBox.instancesList[0]; + if ((bool)simpleDialogBox) + { + firstSelectedObjectProvider.firstSelectedObject = simpleDialogBox.GetComponentInChildren().gameObject; + firstSelectedObjectProvider.ResetLastSelected(); + } + } + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + + public void InviteButtonPressed() + { + if (!PlatformSystems.lobbyManager.isInLobby) + { + NetworkManagerSystem.singleton.CreateLocalLobby(); + } + PlatformSystems.lobbyManager.OpenInviteOverlay(); + } + + private bool ShouldEnableQuickplayButton() + { + return PlatformSystems.lobbyManager.ShouldEnableQuickplayButton(); + } + + private bool ShouldEnableStartPrivateGameButton() + { + return PlatformSystems.lobbyManager.ShouldEnableStartPrivateGameButton(); + } + + private bool ShouldEnableJoinClipboardLobbyButton() + { + if (!PlatformSystems.lobbyManager.newestLobbyData.quickplayQueued) + { + return joinClipboardLobbyButtonController.validClipboardLobbyID; + } + return false; + } + + private bool ShouldEnableFindFriendSessionButton() + { + return PlatformSystems.lobbyManager.ShouldEnableFindFriendSessionButton(); + } + + public void ToggleQuickplay() + { + PlatformSystems.lobbyManager.ToggleQuickplay(); + } + + public override bool IsReadyToLeave() + { + return true; + } + + public bool ShouldEnableBackButton() + { + if (!PlatformSystems.lobbyManager.IsBusy) + { + return _curSubView == Subview.Main; + } + return false; + } + + public void GoBack() + { + if (friendSessionBrowserController.isActiveAndEnabled) + { + friendSessionBrowserController.gameObject.SetActive(value: false); + } + else if (PlatformSystems.lobbyManager.IsQuickPlaySearching() && NetworkManagerSystem.singleton.IsHost()) + { + quickplayButton.InvokeClick(); + } + else if (PlatformSystems.lobbyManager.isInLobby) + { + ResetLobby(); + ResetLastSelected(); + ReturnToMainMenu(); + } + else if (ShouldEnableBackButton()) + { + ReturnToMainMenu(); + } + } + + public void ResetLastSelected() + { + firstSelectedObjectProvider?.ResetLastSelected(); + firstSelectedObjectProvider?.EnsureSelectedObject(); + } + + public void SetQuickplayTextBelowMinPlayers() + { + if (PlatformSystems.lobbyManager.HasMPFeature(MPFeatures.Quickplay)) + { + object[] formatArgs = new object[2] + { + PlatformSystems.lobbyManager.calculatedTotalPlayerCount, + RoR2Application.maxPlayers + }; + SetQuickplayText("STEAM_LOBBY_STATUS_QUICKPLAY_WAITING_BELOW_MINIMUM_PLAYERS", formatArgs); + } + } + + public void UpdateCutoffTimeText(int numberOfPlayers, float timeRemaining) + { + object[] formatArgs = new object[3] + { + numberOfPlayers, + RoR2Application.maxPlayers, + (int)Math.Max(0.0, timeRemaining) + }; + SetQuickplayText("STEAM_LOBBY_STATUS_QUICKPLAY_WAITING_ABOVE_MINIMUM_PLAYERS", formatArgs); + } + + public void SetPendingQuickplayText(string text, object[] formatArgs = null) + { + if (formatArgs == null) + { + formatArgs = Array.Empty(); + } + pendingQuickplayText = Language.GetStringFormatted(text, formatArgs); + } + + public void SetQuickplayText(string text, object[] formatArgs = null) + { + if (formatArgs == null) + { + formatArgs = Array.Empty(); + } + quickplayStateText.text = Language.GetStringFormatted(text, formatArgs); + } + + public void ToggleAllButtonsInteractable(bool interactable) + { + for (int i = 0; i < 8; i++) + { + SetButtonInteractableStatus((MPButtons)i, interactable); + } + firstSelectedObjectProvider.ForceSelectFirstInteractable(); + } + + public void SetButtonInteractableStatus(MPButtons button, bool interactable) + { + MPButton mPButton = null; + switch (button) + { + case MPButtons.HostGame: + mPButton = hostGame; + break; + case MPButtons.FindGame: + mPButton = findGame; + break; + case MPButtons.Quickplay: + mPButton = quickplayButton; + break; + case MPButtons.StartPrivateGame: + mPButton = startPrivateGameButton; + break; + case MPButtons.Invite: + mPButton = inviteButton; + break; + case MPButtons.FindFriendSession: + mPButton = findFriendSessionButton; + break; + case MPButtons.Back: + mPButton = backButton; + break; + case MPButtons.EnterGame: + mPButton = enterGameButton; + break; + } + if (mPButton != null) + { + mPButton.interactable = interactable; + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/PlatformToggle.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/PlatformToggle.cs new file mode 100644 index 0000000..2289b89 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/PlatformToggle.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace RoR2.UI.MainMenu; + +public class PlatformToggle : MonoBehaviour +{ + public bool Steam; + + public bool XboxOne; + + public bool XboxSeries; + + public bool PS4; + + public bool PS5; + + public bool Switch; + + private void Awake() + { + base.gameObject.SetActive(Steam); + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/ProfileMainMenuScreen.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/ProfileMainMenuScreen.cs new file mode 100644 index 0000000..84df8be --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/ProfileMainMenuScreen.cs @@ -0,0 +1,193 @@ +using System.Collections.Generic; +using TMPro; +using UnityEngine; + +namespace RoR2.UI.MainMenu; + +[RequireComponent(typeof(MPEventSystemLocator))] +public class ProfileMainMenuScreen : BaseMainMenuScreen +{ + public GameObject createProfilePanel; + + public TMP_InputField createProfileNameInputField; + + public MPButton submitProfileNameButton; + + public GameObject gotoSelectProfilePanelButtonContainer; + + public GameObject selectProfilePanel; + + public MPButton gotoCreateProfilePanelButton; + + public UserProfileListController existingProfileListController; + + private MPEventSystemLocator eventSystemLocator; + + private bool firstTimeConfiguration; + + private const string defaultName = "Nameless Survivor"; + + private string GuessDefaultProfileName() + { + return PlatformSystems.saveSystem.GetPlatformUsernameOrDefault("Nameless Survivor"); + } + + public UserProfile Editor_TryOpenTestProfile() + { + List availableProfileNames = PlatformSystems.saveSystem.GetAvailableProfileNames(); + if (availableProfileNames.Count > 0) + { + Debug.LogWarning("Got existing profile!"); + return PlatformSystems.saveSystem.GetProfile(availableProfileNames[0]); + } + return null; + } + + public void OpenDefaultProfile() + { + GuessDefaultProfileName(); + UserProfile mainProfile = null; + SetMainProfile(mainProfile); + } + + protected new void Awake() + { + eventSystemLocator = GetComponent(); + existingProfileListController.onProfileSelected += SetMainProfile; + existingProfileListController.onListRebuilt += OnListRebuilt; + } + + protected new void OnEnable() + { + firstTimeConfiguration = true; + List availableProfileNames = PlatformSystems.saveSystem.GetAvailableProfileNames(); + for (int i = 0; i < availableProfileNames.Count; i++) + { + if (IsProfileCustom(PlatformSystems.saveSystem.GetProfile(availableProfileNames[i]))) + { + firstTimeConfiguration = false; + break; + } + } + if (firstTimeConfiguration) + { + OpenCreateProfileMenu(firstTime: true); + return; + } + createProfilePanel.SetActive(value: false); + selectProfilePanel.SetActive(value: true); + OnListRebuilt(); + gotoSelectProfilePanelButtonContainer.SetActive(value: true); + } + + public void OpenCreateProfileMenu(bool firstTime) + { + selectProfilePanel.SetActive(value: false); + createProfilePanel.SetActive(value: true); + createProfileNameInputField.text = GuessDefaultProfileName(); + if (firstTime) + { + gotoSelectProfilePanelButtonContainer.SetActive(value: false); + } + } + + private void OnListRebuilt() + { + existingProfileListController.GetReadOnlyElementsList(); + } + + protected void OnDisable() + { + } + + private void SetMainProfile(UserProfile profile) + { + LocalUserManager.SetLocalUsers(new LocalUserManager.LocalUserInitializationInfo[1] + { + new LocalUserManager.LocalUserInitializationInfo + { + profile = profile + } + }); + if (myMainMenuController != null) + { + myMainMenuController.desiredMenuScreen = myMainMenuController.titleMenuScreen; + } + else + { + Debug.LogError("myMainMenuController reference null on ProfileMainMenuScreen.cs while trying to run SetMainProfile(UserProfile profile)"); + } + } + + private static bool IsProfileCustom(UserProfile profile) + { + return profile.fileName != "default"; + } + + private static bool IsNewProfileNameAcceptable(string newProfileName) + { + if (PlatformSystems.saveSystem.GetProfile(newProfileName) != null) + { + return false; + } + if (newProfileName == "") + { + return false; + } + return true; + } + + public void OnAddProfilePressed() + { + if (eventSystemLocator.eventSystem.currentSelectedGameObject == createProfileNameInputField.gameObject && !Input.GetKeyDown(KeyCode.Return) && !Input.GetKeyDown(KeyCode.KeypadEnter)) + { + return; + } + string text = createProfileNameInputField.text; + if (IsNewProfileNameAcceptable(text)) + { + createProfileNameInputField.text = ""; + UserProfile userProfile = PlatformSystems.saveSystem.CreateProfile(RoR2Application.cloudStorage, text, 0uL); + if (userProfile != null) + { + SetMainProfile(userProfile); + } + } + } + + protected new void Update() + { + if (!eventSystemLocator.eventSystem || eventSystemLocator.eventSystem.player == null || !eventSystemLocator.eventSystem.player.GetButton(31)) + { + return; + } + GameObject currentSelectedGameObject = MPEventSystemManager.combinedEventSystem.currentSelectedGameObject; + if (!currentSelectedGameObject) + { + return; + } + UserProfileListElementController component = currentSelectedGameObject.GetComponent(); + if ((bool)component) + { + if (component.userProfile == null) + { + Debug.LogError("!!!???"); + return; + } + SimpleDialogBox simpleDialogBox = SimpleDialogBox.Create(); + string consoleString = "user_profile_delete \"" + component.userProfile.fileName + "\""; + simpleDialogBox.headerToken = new SimpleDialogBox.TokenParamsPair + { + token = "USER_PROFILE_DELETE_HEADER", + formatParams = null + }; + simpleDialogBox.descriptionToken = new SimpleDialogBox.TokenParamsPair + { + token = "USER_PROFILE_DELETE_DESCRIPTION", + formatParams = new object[1] { component.userProfile.name } + }; + simpleDialogBox.AddCommandButton(consoleString, "USER_PROFILE_DELETE_YES"); + simpleDialogBox.AddCancelButton("USER_PROFILE_DELETE_NO"); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/SignupMainMenuScreen.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/SignupMainMenuScreen.cs new file mode 100644 index 0000000..1effcc1 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/SignupMainMenuScreen.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Net; +using Facepunch.Steamworks; +using HGsignup.Service; +using TMPro; +using UnityEngine; + +namespace RoR2.UI.MainMenu; + +public class SignupMainMenuScreen : BaseMainMenuScreen +{ + private const string environment = "prod"; + + private const string title = "Canary"; + + private static string viewableName = "Signup"; + + [SerializeField] + private TMP_InputField emailInput; + + [SerializeField] + private HGButton submitButton; + + [SerializeField] + private HGButton backButton; + + [SerializeField] + private HGTextMeshProUGUI successText; + + [SerializeField] + private HGTextMeshProUGUI failureText; + + [SerializeField] + private HGTextMeshProUGUI waitingText; + + [SerializeField] + private HGGamepadInputEvent backGamepadInputEvent; + + private SignupClient signupClient; + + private string email; + + private bool awaitingResponse; + + private HashSet successfulEmailSubmissions; + + [SystemInitializer(new Type[] { })] + private static void Init() + { + ViewablesCatalog.AddNodeToRoot(new ViewablesCatalog.Node(viewableName, isFolder: false) + { + shouldShowUnviewed = CheckViewable + }); + } + + private static bool CheckViewable(UserProfile userProfile) + { + return !userProfile.HasViewedViewable("/" + viewableName); + } + + private new void Awake() + { + signupClient = new SignupClient("prod"); + successfulEmailSubmissions = new HashSet(); + } + + private new void OnEnable() + { + waitingText?.gameObject?.SetActive(value: false); + successText?.gameObject?.SetActive(value: false); + failureText?.gameObject?.SetActive(value: false); + if ((bool)backGamepadInputEvent) + { + backGamepadInputEvent.enabled = true; + } + } + + private new void Update() + { + base.Update(); + if ((bool)submitButton) + { + if ((bool)emailInput && SignupClient.IsEmailValid(emailInput.text) && !awaitingResponse && !successfulEmailSubmissions.Contains(emailInput.text)) + { + submitButton.interactable = true; + } + else + { + submitButton.interactable = false; + } + } + if ((bool)backButton) + { + backButton.interactable = !awaitingResponse; + } + if ((bool)backGamepadInputEvent) + { + backGamepadInputEvent.enabled = !awaitingResponse; + } + } + + public void TrySubmit() + { + if (!awaitingResponse && (bool)emailInput && !successfulEmailSubmissions.Contains(emailInput.text) && SignupClient.IsEmailValid(emailInput.text)) + { + email = emailInput.text; + User user = Client.Instance.User; + user.OnEncryptedAppTicketRequestComplete = (Action)Delegate.Combine(user.OnEncryptedAppTicketRequestComplete, new Action(ProcessAppTicketRefresh)); + Client.Instance.User.RequestEncryptedAppTicketAsync(new byte[0]); + awaitingResponse = true; + waitingText?.gameObject?.SetActive(value: true); + successText?.gameObject?.SetActive(value: false); + failureText?.gameObject?.SetActive(value: false); + } + } + + private void ProcessAppTicketRefresh(bool success, byte[] ticket) + { + bool flag = success; + User user = Client.Instance.User; + user.OnEncryptedAppTicketRequestComplete = (Action)Delegate.Remove(user.OnEncryptedAppTicketRequestComplete, new Action(ProcessAppTicketRefresh)); + if (success) + { + if (SignupClient.IsTicketValid(ticket)) + { + if (signupClient != null) + { + signupClient.SignupCompleted += SignupCompleted; + signupClient.SignupSteamAsync(email, "Canary", ticket); + } + } + else + { + Debug.LogError("Can't signup with an invalid ticket!"); + flag = false; + } + } + else + { + Debug.LogError("Failure refreshing Encrypted App Ticket from Steam for mailing list!"); + flag = false; + } + if (!flag) + { + awaitingResponse = false; + waitingText?.gameObject?.SetActive(value: false); + successText?.gameObject?.SetActive(value: false); + failureText?.gameObject?.SetActive(value: true); + } + } + + private void SignupCompleted(string email, HttpStatusCode statusCode) + { + awaitingResponse = false; + waitingText?.gameObject?.SetActive(value: false); + if (statusCode == HttpStatusCode.OK) + { + successfulEmailSubmissions.Add(email); + successText?.gameObject?.SetActive(value: true); + failureText?.gameObject?.SetActive(value: false); + } + else + { + successText?.gameObject?.SetActive(value: false); + failureText?.gameObject?.SetActive(value: true); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/SubmenuMainMenuScreen.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/SubmenuMainMenuScreen.cs new file mode 100644 index 0000000..9094391 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/SubmenuMainMenuScreen.cs @@ -0,0 +1,41 @@ +using UnityEngine; +using UnityEngine.Serialization; + +namespace RoR2.UI.MainMenu; + +public class SubmenuMainMenuScreen : BaseMainMenuScreen +{ + [FormerlySerializedAs("settingsPanelPrefab")] + public GameObject submenuPanelPrefab; + + private GameObject submenuPanelInstance; + + private HGHeaderNavigationController headerNavigationController; + + private new void Awake() + { + submenuPanelInstance = Object.Instantiate(submenuPanelPrefab, base.transform); + submenuPanelInstance.GetComponent().isPrimaryPlayer = true; + headerNavigationController = GetComponentInChildren(); + } + + public override void OnEnter(MainMenuController mainMenuController) + { + submenuPanelInstance.SetActive(value: true); + headerNavigationController?.ChooseFirstHeader(); + base.OnEnter(mainMenuController); + } + + public override void OnExit(MainMenuController mainMenuController) + { + base.OnExit(mainMenuController); + } + + public new void Update() + { + if (!submenuPanelInstance.activeSelf && (bool)myMainMenuController) + { + myMainMenuController.SetDesiredMenuScreen(myMainMenuController.titleMenuScreen); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/TitleMenuController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/TitleMenuController.cs new file mode 100644 index 0000000..a3e2a6b --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.MainMenu/TitleMenuController.cs @@ -0,0 +1,63 @@ +using RoR2.EntityLogic; +using UnityEngine; + +namespace RoR2.UI.MainMenu; + +public class TitleMenuController : MonoBehaviour +{ + public ConsoleFunctions consoleFunctions; + + public MainMenuController mainMenuController; + + public DelayedEvent titleDelayedEvent; + + public CanvasGroup titleButtonPanelCanvas; + + public MultiplayerMenuController multiplayerMenuController; + + public void OnSinglePlayerButtonPressed() + { + if (CanTransitionOutOfTitleMenu()) + { + consoleFunctions.SubmitCmd("transition_command \"gamemode ClassicRun; host 0;\""); + titleDelayedEvent.CallDelayed(0f); + titleButtonPanelCanvas.interactable = false; + mainMenuController.SetAllowTransition(value: false); + } + } + + public void OnMultiplayerButtonPressed() + { + if (CanTransitionOutOfTitleMenu() && RoR2Application.IsAllUsersEntitlementsUpdated) + { + multiplayerMenuController.SetNetworkType(isInternet: true); + mainMenuController.SetDesiredMenuScreen(mainMenuController.multiplayerMenuScreen); + } + } + + public void OnExtraGameModeButtonPressed() + { + if (CanTransitionOutOfTitleMenu()) + { + mainMenuController.SetDesiredMenuScreen(mainMenuController.extraGameModeMenuScreen); + } + } + + public void OnLogbookButtonPressed() + { + if (CanTransitionOutOfTitleMenu()) + { + consoleFunctions.SubmitCmd("transition_command \"set_scene logbook\""); + titleDelayedEvent.CallDelayed(0f); + } + } + + private bool CanTransitionOutOfTitleMenu() + { + if (RoR2Application.IsMainMenuInitialized && RoR2Application.IsEntitlementsUpdated) + { + return !FadeToBlackManager.IsFading(); + } + return false; + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.SkinControllers/BaseSkinController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.SkinControllers/BaseSkinController.cs new file mode 100644 index 0000000..f8627f9 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.SkinControllers/BaseSkinController.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace RoR2.UI.SkinControllers; + +[ExecuteAlways] +public abstract class BaseSkinController : MonoBehaviour +{ + public UISkinData skinData; + + protected abstract void OnSkinUI(); + + protected void Awake() + { + if ((bool)skinData) + { + DoSkinUI(); + } + } + + private void DoSkinUI() + { + if ((bool)skinData) + { + OnSkinUI(); + } + } +} diff --git a/ilspy_dump/ror2_csproj/RoR2.UI.SkinControllers/ButtonSkinController.cs b/ilspy_dump/ror2_csproj/RoR2.UI.SkinControllers/ButtonSkinController.cs new file mode 100644 index 0000000..3f73f55 --- /dev/null +++ b/ilspy_dump/ror2_csproj/RoR2.UI.SkinControllers/ButtonSkinController.cs @@ -0,0 +1,127 @@ +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace RoR2.UI.SkinControllers; + +[RequireComponent(typeof(Button))] +public class ButtonSkinController : BaseSkinController +{ + private static readonly List instancesList = new List(); + + private Button button; + + public bool useRecommendedButtonWidth = true; + + public bool useRecommendedButtonHeight = true; + + public bool useRecommendedImage = true; + + public bool useRecommendedMaterial = true; + + public bool useRecommendedAlignment = true; + + public bool useRecommendedLabel = true; + + private LayoutElement layoutElement; + + private void CacheComponents() + { + button = GetComponent