feat: add ilspy dump for ror2.dll
parent
98d34ebbac
commit
6ff22c6d47
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
public static class AkGameObjUtil
|
||||
{
|
||||
public static void SetAkGameObjectStatic(GameObject gameObj, bool staticSetting)
|
||||
{
|
||||
if (gameObj.TryGetComponent<AkGameObj>(out var component))
|
||||
{
|
||||
component.isStaticAfterDelay = staticSetting;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Assets.RoR2.Scripts.Platform.PS5;
|
||||
|
||||
public class OnScreenLog : MonoBehaviour
|
||||
{
|
||||
}
|
|
@ -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<BaseActivity> activities;
|
||||
|
||||
public BaseActivity LookupActivityByID(string activityID)
|
||||
{
|
||||
foreach (BaseActivity activity in activities)
|
||||
{
|
||||
if (activity.ActivityID == activityID)
|
||||
{
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<BaseActivity> CompareActivityCriteria(BaseActivitySelector activitySelector)
|
||||
{
|
||||
List<BaseActivity> list = new List<BaseActivity>();
|
||||
foreach (BaseActivity activity in activities)
|
||||
{
|
||||
if (activitySelector.IsCompatibleWith(activity))
|
||||
{
|
||||
list.Add(activity);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -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<string, BaseActivity> InProgressActivities = new Dictionary<string, BaseActivity>();
|
||||
|
||||
protected Dictionary<string, BaseActivity> AvailableActivities = new Dictionary<string, BaseActivity>();
|
||||
|
||||
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<NetworkUser> 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<BaseActivity.ActivitySurvivor>(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<LocalUser>.OnAllUserEntitlementsUpdated = (Action)Delegate.Remove(BaseUserEntitlementTracker<LocalUser>.OnAllUserEntitlementsUpdated, new Action(OnEntitlementsChangedCallback));
|
||||
BaseUserEntitlementTracker<LocalUser>.OnAllUserEntitlementsUpdated = (Action)Delegate.Combine(BaseUserEntitlementTracker<LocalUser>.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<ActivityData> handle = Addressables.LoadAssetAsync<ActivityData>("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<BaseActivity> 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());
|
||||
}
|
||||
}
|
|
@ -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!");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<EventResponse> OnGameIntentReceivedEvent;
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ClearPendingGameIntent()
|
||||
{
|
||||
}
|
||||
|
||||
protected void FireGameIntentReceived()
|
||||
{
|
||||
EventResponse eventResponse = new EventResponse();
|
||||
this.OnGameIntentReceivedEvent?.Invoke(eventResponse);
|
||||
if (eventResponse.wasEventHandledByAnySystem)
|
||||
{
|
||||
ClearPendingGameIntent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
public static class AutomatedBuildVersion
|
||||
{
|
||||
public const string buildVersionString = "290";
|
||||
}
|
|
@ -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<Transform>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(LineRenderer))]
|
||||
[ExecuteAlways]
|
||||
public class BezierCurveLine : MonoBehaviour
|
||||
{
|
||||
private Vector3[] vertexList = Array.Empty<Vector3>();
|
||||
|
||||
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<LineRenderer>();
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<FireProjectileInfo> cachedCleaverProjectileInfo = new Queue<FireProjectileInfo>();
|
||||
|
||||
private Dictionary<ushort, CleaverProjectile> cleaverDictionary = new Dictionary<ushort, CleaverProjectile>();
|
||||
|
||||
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<CharacterBody>();
|
||||
}
|
||||
chefAnimator = characterBody.modelLocator.modelTransform.GetComponent<Animator>();
|
||||
}
|
||||
|
||||
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<NetworkIdentity>().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<NetworkIdentity>().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()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<NameTransformPair>();
|
||||
|
||||
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<T>(string childName)
|
||||
{
|
||||
return FindChildComponent<T>(FindChildIndex(childName));
|
||||
}
|
||||
|
||||
public T FindChildComponent<T>(int childIndex)
|
||||
{
|
||||
Transform transform = FindChild(childIndex);
|
||||
if (!transform)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
return transform.GetComponent<T>();
|
||||
}
|
||||
}
|
|
@ -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<LODGroup>();
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class DelusionPickerController : MonoBehaviour
|
||||
{
|
||||
private void Start()
|
||||
{
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<ParticleSystem>();
|
||||
}
|
||||
if (!efh)
|
||||
{
|
||||
efh = GetComponent<EffectManagerHelper>();
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if ((bool)trackedParticleSystem && !trackedParticleSystem.IsAlive())
|
||||
{
|
||||
if ((bool)efh && efh.OwningPool != null)
|
||||
{
|
||||
efh.OwningPool.ReturnObject(efh);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object.Destroy(base.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(AudioSource))]
|
||||
public class DestroyOnSoundEnd : MonoBehaviour
|
||||
{
|
||||
private AudioSource audioSource;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!audioSource.isPlaying)
|
||||
{
|
||||
Object.Destroy(base.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<TeamIndex>(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<AlternateButtonEvents>();
|
||||
if ((bool)component)
|
||||
{
|
||||
component.InvokeAltClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AttemptTertiaryClick()
|
||||
{
|
||||
if ((bool)eventSystem.currentSelectedButton)
|
||||
{
|
||||
AlternateButtonEvents component = eventSystem.currentSelectedButton.GetComponent<AlternateButtonEvents>();
|
||||
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<HealthComponent>();
|
||||
component.godMode = !component.godMode;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartLog()
|
||||
{
|
||||
}
|
||||
|
||||
public void StopLog()
|
||||
{
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
UnityEngine.Object.Destroy(base.gameObject);
|
||||
}
|
||||
}
|
|
@ -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<NodeGraph.NodeIndex> 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<CharacterMaster>();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class DisableOnStart : MonoBehaviour
|
||||
{
|
||||
private void Start()
|
||||
{
|
||||
base.gameObject.SetActive(value: false);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<DynamicBoneCollider> m_Colliders;
|
||||
|
||||
public List<Transform> 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<Particle> m_Particles = new List<Particle>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<object>()
|
||||
};
|
||||
dialogBox.descriptionToken = new SimpleDialogBox.TokenParamsPair
|
||||
{
|
||||
token = messageText,
|
||||
formatParams = Array.Empty<object>()
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ElectricEffect : MonoBehaviour
|
||||
{
|
||||
public LineRenderer lightningLineRenderer;
|
||||
|
||||
public List<Texture> lightningTextures = new List<Texture>();
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
public delegate void EmptyDelegate();
|
|
@ -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<Light>();
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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<Field> stateFieldList = new List<Field>();
|
||||
|
||||
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<SerializeField>(fieldInfo, inherit: true).Any();
|
||||
}
|
||||
|
||||
private static bool FieldLacksNonSerializedAttribute(FieldInfo fieldInfo)
|
||||
{
|
||||
return !CustomAttributeExtensions.GetCustomAttributes<NonSerializedAttribute>(fieldInfo, inherit: true).Any();
|
||||
}
|
||||
|
||||
public void SetStateType(Type stateType)
|
||||
{
|
||||
serializedType.stateType = stateType;
|
||||
stateType = serializedType.stateType;
|
||||
if (stateType == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
IEnumerable<FieldInfo> first = stateType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Where(FieldHasSerializeAttribute);
|
||||
IEnumerable<FieldInfo> second = (from fieldInfo in stateType.GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
where fieldInfo.DeclaringType == stateType
|
||||
select fieldInfo).Where(FieldLacksNonSerializedAttribute);
|
||||
List<FieldInfo> list = first.Concat(second).ToList();
|
||||
Dictionary<FieldInfo, Field> dictionary = new Dictionary<FieldInfo, Field>();
|
||||
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<EntityState> GenerateInstanceFieldInitializerDelegate()
|
||||
{
|
||||
Type stateType = serializedType.stateType;
|
||||
if (stateType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<FieldValuePair> list = new List<FieldValuePair>();
|
||||
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<Field> GetFields()
|
||||
{
|
||||
return stateFieldList.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private List<StateInfo> stateInfoList = new List<StateInfo>();
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private string endMarker = "GIT_END";
|
||||
|
||||
private static readonly Dictionary<Type, Action<EntityState>> instanceFieldInitializers = new Dictionary<Type, Action<EntityState>>();
|
||||
|
||||
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<object> 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<EntityState> 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<StateInfo> list = new List<StateInfo>();
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<CharacterMaster>();
|
||||
ai = GetComponent<BaseAI>();
|
||||
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<NodeGraphSpider.StepInfo> 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
namespace EntityStates.AcidLarva;
|
||||
|
||||
public class SpawnState : GenericCharacterSpawnState
|
||||
{
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<HealthComponent> list = new List<HealthComponent>();
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<TeamComponent>().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<DelayBlast>();
|
||||
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<TeamFilter>().teamIndex = TeamComponent.GetObjectTeam(component.attacker);
|
||||
obj.transform.localScale = new Vector3(radius, radius, 1f);
|
||||
ScaleParticleSystemDuration component2 = obj.GetComponent<ScaleParticleSystemDuration>();
|
||||
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<TeamComponent> 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;
|
||||
}
|
||||
}
|
|
@ -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<ChildLocator>();
|
||||
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<DelayBlast>();
|
||||
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<TeamFilter>().teamIndex = TeamComponent.GetObjectTeam(component.attacker);
|
||||
obj.transform.localScale = new Vector3(radius, radius, 1f);
|
||||
ScaleParticleSystemDuration component2 = obj.GetComponent<ScaleParticleSystemDuration>();
|
||||
if ((bool)component2)
|
||||
{
|
||||
component2.newDuration = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (base.fixedAge >= duration && base.isAuthority)
|
||||
{
|
||||
outer.SetNextState(new FireBomb());
|
||||
}
|
||||
}
|
||||
|
||||
public override InterruptPriority GetMinimumInterruptPriority()
|
||||
{
|
||||
return InterruptPriority.Skill;
|
||||
}
|
||||
}
|
|
@ -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<ChildLocator>();
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<TeamComponent>();
|
||||
if (!component)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
teamIndex = component.teamIndex;
|
||||
if (teamIndex != excludedTeam)
|
||||
{
|
||||
CharacterMotor component2 = collider.GetComponent<CharacterMotor>();
|
||||
if ((bool)component2)
|
||||
{
|
||||
component2.ApplyForce(normalized * force);
|
||||
}
|
||||
Rigidbody component3 = collider.GetComponent<Rigidbody>();
|
||||
if ((bool)component3)
|
||||
{
|
||||
component3.AddForce(normalized * force, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
HGPhysics.ReturnResults(colliders);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<ChildLocator>();
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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<ChildLocator>();
|
||||
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<TeamComponent>();
|
||||
if (!component)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
teamIndex = component.teamIndex;
|
||||
if (teamIndex != excludedTeam)
|
||||
{
|
||||
CharacterMotor component2 = collider.GetComponent<CharacterMotor>();
|
||||
if ((bool)component2)
|
||||
{
|
||||
component2.ApplyForce(normalized * force);
|
||||
}
|
||||
Rigidbody component3 = collider.GetComponent<Rigidbody>();
|
||||
if ((bool)component3)
|
||||
{
|
||||
component3.AddForce(normalized * force, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
HGPhysics.ReturnResults(colliders);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
using EntityStates.GreaterWispMonster;
|
||||
|
||||
namespace EntityStates.ArchWispMonster;
|
||||
|
||||
public class DeathState : EntityStates.GreaterWispMonster.DeathState
|
||||
{
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
using EntityStates.GreaterWispMonster;
|
||||
|
||||
namespace EntityStates.ArchWispMonster;
|
||||
|
||||
public class FireCannons : EntityStates.GreaterWispMonster.FireCannons
|
||||
{
|
||||
}
|
|
@ -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<PurchaseInteraction>();
|
||||
if ((object)purchaseInteraction != null)
|
||||
{
|
||||
purchaseInteraction.costType = interactionCostType;
|
||||
purchaseInteraction.Networkcost = interactionCost;
|
||||
purchaseInteraction.Networkavailable = interactionAvailable;
|
||||
purchaseInteraction.onPurchase.AddListener(DoOnPurchase);
|
||||
}
|
||||
rayParticleSystem = FindModelChild("RayParticles")?.GetComponent<ParticleSystem>();
|
||||
postProcessVolume = FindModelChild("PP")?.GetComponent<PostProcessVolume>();
|
||||
light = FindModelChild("Light").GetComponent<Light>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<SfxLocator>().deathSound, base.gameObject);
|
||||
}
|
||||
|
||||
public override void FixedUpdate()
|
||||
{
|
||||
base.FixedUpdate();
|
||||
if (base.fixedAge > duration)
|
||||
{
|
||||
EntityState.Destroy(base.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public override InterruptPriority GetMinimumInterruptPriority()
|
||||
{
|
||||
return InterruptPriority.Death;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>(), (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<CharacterDirection>();
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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<AimAnimator>();
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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<BaseAI>().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>(), (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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<Animator>();
|
||||
characterModel = modelTransform.GetComponent<CharacterModel>();
|
||||
hurtboxGroup = modelTransform.GetComponent<HurtBoxGroup>();
|
||||
if ((bool)smokeEffectPrefab)
|
||||
{
|
||||
Transform transform = modelTransform;
|
||||
if ((bool)transform)
|
||||
{
|
||||
smokeEffectInstance = Object.Instantiate(smokeEffectPrefab, transform);
|
||||
ScaleParticleSystemDuration component = smokeEffectInstance.GetComponent<ScaleParticleSystemDuration>();
|
||||
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<CharacterModel>();
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<GameObject>("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;
|
||||
}
|
||||
}
|
|
@ -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<AurelioniteHeartController>();
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace EntityStates.AurelioniteHeart;
|
||||
|
||||
public class AurelioniteHeartIdleState : AurelioniteHeartEntityState
|
||||
{
|
||||
public override void OnEnter()
|
||||
{
|
||||
base.OnEnter();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace EntityStates.Bandit2.Weapon;
|
||||
|
||||
public class PrepSidearmResetRevolver : BasePrepSidearmRevolverState
|
||||
{
|
||||
protected override EntityState GetNextState()
|
||||
{
|
||||
return new FireSidearmResetRevolver();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace EntityStates.Bandit2.Weapon;
|
||||
|
||||
public class PrepSidearmSkullRevolver : BasePrepSidearmRevolverState
|
||||
{
|
||||
protected override EntityState GetNextState()
|
||||
{
|
||||
return new FireSidearmSkullRevolver();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<ChildLocator>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace EntityStates.Barrel;
|
||||
|
||||
public class Closed : EntityState
|
||||
{
|
||||
public override void OnEnter()
|
||||
{
|
||||
base.OnEnter();
|
||||
PlayAnimation("Body", "Closed");
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue