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