using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using AppearancePlus.Animation;
using AppearancePlus.AssetBundles;
using AppearancePlus.Utils;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Events;
using UnityEngine.Playables;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AppearancePlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+d704071c1f6e04f8189d7a278c45d972d8a30d31")]
[assembly: AssemblyProduct("Template plugin for Atlyss using BepInEx 5")]
[assembly: AssemblyTitle("AppearancePlus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace AppearancePlus
{
[BepInPlugin("Nuilescent.AppearancePlus", "Appearance+", "3.8.1")]
internal class AppearancePlus : BaseUnityPlugin
{
public static string DllPath;
public static ScriptablePlayerRace[] ScriptablePlayerRaces;
public static Player Player;
public static List<PlayerRaceModel> PlayerModels = new List<PlayerRaceModel>();
public static List<PlayerVisual> PlayerVisuals = new List<PlayerVisual>();
public static Dictionary<string, NetNPC> NamedNPCs = new Dictionary<string, NetNPC>();
public static List<NetNPC> NetNPCs = new List<NetNPC>();
public static CameraFunction Camera;
public static ChatBehaviour Chat;
public static UnityEvent OnInitialized = new UnityEvent();
public static UnityEvent OnChatInitialized = new UnityEvent();
private static PlayerVisual _playerVisual;
private static PlayerRaceModel _playerModel;
public static PlayerVisual PlayerVisual
{
get
{
if ((Object)(object)_playerVisual == (Object)null || !((Component)_playerVisual).gameObject.activeInHierarchy)
{
_playerVisual = PlayerVisuals.Find((PlayerVisual pv) => (Object)(object)pv != (Object)null && ((Component)pv).gameObject.activeInHierarchy);
}
return _playerVisual;
}
set
{
_playerVisual = value;
}
}
public static PlayerRaceModel PlayerModel
{
get
{
if ((Object)(object)_playerModel == (Object)null || !((Component)_playerModel).gameObject.activeInHierarchy)
{
_playerModel = PlayerModels.Find((PlayerRaceModel pm) => (Object)(object)pm != (Object)null && ((Component)pm).gameObject.activeInHierarchy);
}
return _playerModel;
}
set
{
_playerModel = value;
}
}
private void Awake()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
DllPath = ((BaseUnityPlugin)this).Info.Location.Replace("AppearancePlus.dll", "");
Harmony val = new Harmony("AppearancePlus");
try
{
val.PatchAll();
}
catch (Exception value)
{
System.Console.WriteLine(value);
throw;
}
Console.Initialize(((BaseUnityPlugin)this).Logger);
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void Start()
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Expected O, but got Unknown
Console.Info("A* Location: " + DllPath, LogLocation.ConsoleAndIngame);
Configuration.LoadValues();
if (PathUtils.GetDirectory(DllPath, "CustomTextures", out var result))
{
Console.Info("CustomTextures folder found at: " + result, LogLocation.ConsoleAndIngame);
TextureLoader.LoadTextures(result);
}
else
{
Console.Info("Couldn't find a CustomTextures folder at: " + DllPath, LogLocation.ConsoleAndIngame);
}
OnChatInitialized.AddListener(new UnityAction(InitCommands));
OnInitialized.Invoke();
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
PlayerModels.RemoveAll((PlayerRaceModel prm) => (Object)(object)prm == (Object)null);
PlayerVisuals.RemoveAll((PlayerVisual pv) => (Object)(object)pv == (Object)null);
if ((Object)(object)PlayerVisual != (Object)null)
{
Configuration.LoadValues(ConfigType.Slider);
if ((Object)(object)PlayerModel != (Object)null)
{
PlayerModel.Apply_CharacterDisplay();
}
PlayerAppearanceStruct playerAppearanceStruct = PlayerVisual._playerAppearanceStruct;
PlayerAppearance_Profile appearanceProfile = ProfileDataManager._current._characterFile._appearanceProfile;
playerAppearanceStruct._bellyWeight = appearanceProfile._bellyWeight;
playerAppearanceStruct._boobWeight = appearanceProfile._boobWeight;
playerAppearanceStruct._bottomWeight = appearanceProfile._bottomWeight;
playerAppearanceStruct._armWeight = appearanceProfile._armWeight;
playerAppearanceStruct._heightWeight = appearanceProfile._heightWeight;
playerAppearanceStruct._widthWeight = appearanceProfile._widthWeight;
playerAppearanceStruct._muzzleWeight = appearanceProfile._muzzleWeight;
playerAppearanceStruct._torsoWeight = appearanceProfile._torsoWeight;
playerAppearanceStruct._voicePitch = appearanceProfile._voicePitch;
PlayerVisual playerVisual = PlayerVisual;
PlayerAppearanceStruct playerAppearanceStruct2 = (PlayerVisual.Network_playerAppearanceStruct = playerAppearanceStruct);
playerVisual._playerAppearanceStruct = playerAppearanceStruct2;
PlayerVisual.Cmd_SendNew_PlayerAppearanceStruct(playerAppearanceStruct);
PlayerVisual.Apply_NetworkedCharacterDisplay();
}
}
private void InitCommands()
{
Commands.Add(new CommandInfo("help", "Print every command and their description.", "", (Func<bool>)delegate
{
Commands.PrintCommands();
return true;
}));
Commands.Add(new CommandInfo("anim player", "", "Play animation clip on player", (Func<bool>)delegate
{
Console.Info("Playing Animation DefaultDance.", LogLocation.ConsoleAndIngame);
return PlayableGraphManager.PlayAnimationClip(PlayerModel, "DefaultDance", loop: false);
}));
Commands.Add(new CommandInfo("console", "<true/false> Enable/Disable the in-game console.", "", Console.ToggleConsole));
Commands.Add(new CommandInfo("size", "<float> Set the size value for this character.", "Applied character's size value successfully.", SliderLoader.SizeCommand));
Commands.Add(new CommandInfo("zoom", "<float> Set the max zoom.", "Applied max zoom value successfully.", (string p1) => Commands.CmdParseFloat(p1, out Configuration.Zoom.y)));
Commands.Add(new CommandInfo("reload all", "Reloads the config values & textures and applies everything.", "Reloaded everything.", (Func<bool>)delegate
{
Configuration.LoadValues();
SliderLoader.SetValues();
DBonesLoader.SetAll();
TextureLoader.ReloadAllTextures();
return true;
}));
Commands.Add(new CommandInfo("reload config", "Reloads all the config values.", "Reloaded config values. This doesn't apply sliders, dbones or textures! Use /reload all instead.", (Func<bool>)delegate
{
Configuration.LoadValues();
return true;
}));
Commands.Add(new CommandInfo("reload sliders", "Reloads the config values for sliders and applies them.", "Applied Slider Values", (Func<bool>)delegate
{
Configuration.LoadValues(ConfigType.Slider);
SliderLoader.SetValues();
return true;
}));
Commands.Add(new CommandInfo("reload dbones", "Reloads the config values and applies new values to dynamic bones.", "Refreshed Dynamic Bones", (Func<bool>)delegate
{
Configuration.LoadValues(ConfigType.DynamicBone);
DBonesLoader.SetAll();
return true;
}));
Commands.Add(new CommandInfo("reload textures", "Reloads Textures in CustomTextures and applies new ones. Does not revert missing ones to default.", "Applied Custom Textures", (Func<bool>)delegate
{
TextureLoader.ReloadAllTextures();
return true;
}));
Commands.Add(new CommandInfo("print dbones", "Prints the current dynamic bone values.", "", DBonesLoader.PrintCurrentValues));
Commands.Add(new CommandInfo("print sliders", "Prints the current slider values for this character.", "", SliderLoader.PrintCurrentValues));
}
private void InitEmotes()
{
Commands.AddEmote(new EmoteInfo("Fortnite Dance", "fortnite", "DefaultDance", "doing a fortnite", loop: false));
}
private void Update()
{
Console.Update();
}
}
[HarmonyPatch(typeof(MainMenuManager), "Start")]
public static class MenuPatch
{
[HarmonyPostfix]
private static void StartPatch(MainMenuManager __instance)
{
__instance._versionDisplayText.text = Application.version + " w/ A+";
Console.Info("Loaded AppearancePlus!");
}
}
[HarmonyPatch(typeof(PlayerVisual), "RenderPlayerModel")]
public static class PlayerVisualRenderPatch
{
[HarmonyPrefix]
public static bool RenderPlayerModel_Prefx(PlayerVisual __instance)
{
if (!Configuration.ShowPlayerAlways)
{
return true;
}
__instance.Emit_RenderDisplay(true);
return false;
}
}
[HarmonyPatch(typeof(CameraCollision), "LateUpdate")]
public static class CameraCollisionLateUpdatePatch
{
private static float _lastMaxDistance = 25f;
[HarmonyPostfix]
public static void LateUpdate_Postfix(CameraCollision __instance)
{
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
if ((Configuration.Zoom.x == -2f && Configuration.Zoom.y == 60f && !Configuration.ShowPlayerAlways) || !Object.op_Implicit((Object)(object)Player._mainPlayer))
{
return;
}
float num = 0f;
float lastMaxDistance = _lastMaxDistance;
float num2 = _lastMaxDistance;
if (!Player._mainPlayer._inUI && !Player._mainPlayer._inChat && !Player._mainPlayer._bufferingStatus)
{
float axis = Input.GetAxis("Mouse ScrollWheel");
if (axis != 0f)
{
num += axis * 35.5f;
}
}
lastMaxDistance = _lastMaxDistance + num;
if (__instance.Handle_DetectGroundLayer())
{
num2 = ((RaycastHit)(ref __instance.hit)).distance * __instance.step;
}
lastMaxDistance = Mathf.Clamp(lastMaxDistance, Configuration.Zoom.x, Configuration.Zoom.y);
((Component)__instance).transform.localPosition = __instance.dollyDir * Mathf.Min(num2, lastMaxDistance);
_lastMaxDistance = lastMaxDistance;
}
}
[HarmonyPatch(typeof(CameraFunction), "Awake")]
public static class CameraFunctionAwakePatch
{
[HarmonyPostfix]
private static void AwakePostfix(CameraFunction __instance)
{
if (Object.op_Implicit((Object)(object)Player._mainPlayer))
{
AppearancePlus.Camera = __instance;
}
}
}
[HarmonyPatch(typeof(PlayerVisual), "Start")]
public static class PlayerVisualsStartPatch
{
[HarmonyPostfix]
public static void Start_Postfix(PlayerVisual __instance)
{
if ((Object)(object)__instance._player == (Object)(object)Player._mainPlayer)
{
AppearancePlus.PlayerVisual = __instance;
}
}
}
[HarmonyPatch(typeof(PlayerRaceModel), "Awake")]
public static class PlayerRaceModelAwakePatch
{
[HarmonyPostfix]
private static void AwakePostfix(PlayerRaceModel __instance)
{
AppearancePlus.PlayerModels.Add(__instance);
DBonesLoader.SetValues(__instance);
SliderLoader.SetValues();
if ((Object)(object)__instance._player == (Object)(object)Player._mainPlayer)
{
AppearancePlus.PlayerModel = __instance;
}
}
}
[HarmonyPatch(typeof(CharacterCreationManager), "Awake")]
public static class CharacterCreationManagerPatch
{
[HarmonyPostfix]
private static void AwakePostfix(CharacterCreationManager __instance)
{
AppearancePlus.ScriptablePlayerRaces = __instance._scriptablePlayerRaces;
DBonesLoader.SetAll();
SliderLoader.SetValues();
TextureLoader.ApplyCustomTextures();
}
}
[HarmonyPatch(typeof(NetNPC), "Start")]
public static class NetNPCStartPatch
{
[HarmonyPrefix]
public static void Start_Prefix(NetNPC __instance)
{
AppearancePlus.NetNPCs.Add(__instance);
TextureLoader.ReplaceNPCTextures(__instance);
}
}
[HarmonyPatch(typeof(CreepBehavior), "Awake")]
public static class CreepAwakePatch
{
[HarmonyPrefix]
public static void Start_Prefix(CreepBehavior __instance)
{
TextureLoader.ReplaceCreepTextures(__instance);
TextureChangeAnimEvent textureAnim = default(TextureChangeAnimEvent);
if (((Component)__instance).TryGetComponent<TextureChangeAnimEvent>(ref textureAnim))
{
TextureLoader.ReplaceTextureAnim(textureAnim);
}
}
}
public static class Configuration
{
public static Dictionary<string, List<(string, float)>> DynamicBoneValues = new Dictionary<string, List<(string, float)>>();
public static Dictionary<string, List<(string, (float, float))>> RaceDisplayValues = new Dictionary<string, List<(string, (float, float))>>();
public static bool IngameConsole = true;
public static Vector2 Zoom = new Vector2(-2f, 60f);
public static bool ShowPlayerAlways = false;
public static bool ConfigEmpty = true;
public static List<string> races = new List<string> { "imp", "poon", "chang", "kubold", "byrdle" };
public static List<string> raceProperties = new List<string> { "height", "width", "torso", "chest", "arms", "belly", "bottom", "head", "muzzle", "voice" };
public static List<string> dbProperties = new List<string> { "damping", "elasticity", "stiffness", "inert" };
public static void LoadValues(ConfigType configType = ConfigType.Any)
{
string[] files = Directory.GetFiles(AppearancePlus.DllPath, "AppearancePlus_Config.txt", SearchOption.AllDirectories);
if (files.Length == 0)
{
Console.Error("Could not find config file! \nMake sure AppearancePlus_Config.txt exists in ATLYSS/BepInEx/plugins/AppearancePlus");
return;
}
if (files.Length > 1)
{
Console.Warning("Found multiple AppearancePlus_Config.txt. Only first one will be used!");
}
string text = files.First();
Console.Info("Found config file at: " + text);
DynamicBoneValues.Clear();
RaceDisplayValues.Clear();
StreamReader streamReader = new StreamReader(text);
string text2 = streamReader.ReadLine();
int num = 0;
int num2 = 0;
StringBuilder stringBuilder = new StringBuilder();
Console.Info("Reading Config...");
ConfigEmpty = true;
string race;
for (; text2 != null; text2 = streamReader.ReadLine())
{
if (Utility.IsNullOrWhiteSpace(text2))
{
continue;
}
if (ConfigEmpty)
{
ConfigEmpty = false;
}
List<string> list = text2.Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList();
if (text2.StartsWith("//") || text2 == string.Empty || list.Count == 0)
{
continue;
}
if (text2.StartsWith("end"))
{
break;
}
if (configType == ConfigType.Any)
{
if (text2.StartsWith("disable console"))
{
IngameConsole = false;
continue;
}
if (text2.StartsWith("enable console"))
{
IngameConsole = true;
continue;
}
if (text2.StartsWith("zoom"))
{
if (list.Count != 2)
{
if (list.Count < 1)
{
Console.Error("zoom property needs a value.", LogLocation.ConsoleAndIngame);
}
else
{
Console.Error("Don't write any other values after zoom <true/false>:<min>/<max>.", LogLocation.ConsoleAndIngame);
}
}
string[] array = list.Last().Split(':');
if (array.Length != 2)
{
Console.Error("Incorrect syntax for zoom.", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <true/false>:<min>/<max>", LogLocation.ConsoleAndIngame);
continue;
}
if (!bool.TryParse(array[0], out var result))
{
Console.Error("Incorrect syntax for zoom.", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <true/false>:<min>/<max>", LogLocation.ConsoleAndIngame);
continue;
}
string[] array2 = array.Last().Split('/');
float result2;
float result3;
if (array.Length != 2)
{
Console.Error("Incorrect syntax for value " + array[1] + " of " + array[0] + ".", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <min>/<max>", LogLocation.ConsoleAndIngame);
if (text2.Contains(" / "))
{
Console.Warning("Do not use spaces on either sides of '/' symbol.", LogLocation.ConsoleAndIngame);
}
}
else if (!float.TryParse(array2[0], NumberStyles.Any, CultureInfo.InvariantCulture, out result2) || !float.TryParse(array2[1], NumberStyles.Any, CultureInfo.InvariantCulture, out result3))
{
Console.Error("Cannot parse min/max value " + array[1] + " of " + array[0] + ".", LogLocation.ConsoleAndIngame);
Console.Warning("Value should be written like: 0.12, no comma.", LogLocation.ConsoleAndIngame);
}
else
{
ShowPlayerAlways = result;
Zoom.x = result2;
Zoom.y = result3;
}
continue;
}
}
if (list.First() == "character" && (configType == ConfigType.Any || configType == ConfigType.Slider))
{
if (list.Count < 3)
{
Console.Error("Invalid syntax for a character edit.", LogLocation.ConsoleAndIngame);
Console.Warning("Should be: character <race> <property>:<min>/<max>", LogLocation.ConsoleAndIngame);
continue;
}
list.RemoveAt(0);
race = list.First().ToLower();
if (races.All((string r) => r != race))
{
Console.Error(race + " isn't a valid race. Skipping.", LogLocation.ConsoleAndIngame);
continue;
}
list.RemoveAt(0);
RaceDisplayValues.Add(race, new List<(string, (float, float))>());
stringBuilder.Append("\n-> (" + race + ") Saving Properties:");
foreach (string item in list)
{
string[] propertySplit2 = item.Split(':');
if (propertySplit2.Length != 2)
{
Console.Error("Incorrect syntax for " + item + ".", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <property>:<min>/<max>", LogLocation.ConsoleAndIngame);
break;
}
if (raceProperties.All((string p) => p != propertySplit2[0]))
{
Console.Error("No matching race slider properties found for " + propertySplit2[0] + ".", LogLocation.ConsoleAndIngame);
break;
}
string[] array3 = propertySplit2.Last().Split('/');
if (propertySplit2.Length != 2)
{
Console.Error("Incorrect syntax for value " + propertySplit2[1] + " of " + propertySplit2[0] + ".", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <min>/<max>");
if (text2.Contains(" / "))
{
Console.Warning("Do not use spaces on either sides of '/' symbol.");
}
break;
}
if (!float.TryParse(array3[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var result4) || !float.TryParse(array3[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var result5))
{
Console.Error("Cannot parse min/max value " + propertySplit2[1] + " of " + propertySplit2[0] + ".");
Console.Warning("Value should be written like: 0.12, no comma.", LogLocation.ConsoleAndIngame);
break;
}
RaceDisplayValues[race].Add((propertySplit2[0], (result4, result5)));
stringBuilder.Append($"{propertySplit2[0]}:{result4}/{result5} ✔ | ");
num2++;
}
}
else
{
if (!(list.First() == "bone") || (configType != 0 && configType != ConfigType.DynamicBone))
{
continue;
}
if (list.Count < 3)
{
Console.Error("Invalid syntax for a bone edit.", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <bone>:<bodypart> <property>:<value>", LogLocation.ConsoleAndIngame);
break;
}
list.RemoveAt(0);
string text3 = list.First();
list.RemoveAt(0);
DynamicBoneValues.Add(text3, new List<(string, float)>());
stringBuilder.Append("\n-> (" + text3 + ") Saving Properties:");
foreach (string item2 in list)
{
string[] propertySplit = item2.Split(':');
if (propertySplit.Length != 2)
{
Console.Error("Invalid syntax for " + propertySplit[0] + ".", LogLocation.ConsoleAndIngame);
Console.Warning("Should be <property>:<value>.", LogLocation.ConsoleAndIngame);
if (text2.Contains(" : "))
{
Console.Warning("Do not use spaces on either sides of ':' symbol.", LogLocation.ConsoleAndIngame);
}
break;
}
propertySplit[0] = propertySplit[0].ToLower();
propertySplit[1] = propertySplit[1].ToLower();
if (dbProperties.All((string p) => p != propertySplit[0]))
{
Console.Warning("No matching dynamic bone properties found for " + propertySplit[0] + ".", LogLocation.ConsoleAndIngame);
break;
}
if (!float.TryParse(propertySplit[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var result6))
{
Console.Error("Cannot parse value " + propertySplit[1] + " of " + propertySplit[0] + ". Value should be written like: 0.12, no comma.", LogLocation.ConsoleAndIngame);
break;
}
if (result6 < 0f || result6 > 1f)
{
Console.Error("Invalid value " + propertySplit[1] + " of " + propertySplit[0] + ". Value should be between 0 and 1.", LogLocation.ConsoleAndIngame);
break;
}
DynamicBoneValues[text3].Add((propertySplit[0], result6));
stringBuilder.Append(propertySplit[0] + ":" + propertySplit[1] + " ✔ | ");
num++;
}
}
}
if (!ConfigEmpty)
{
if (configType == ConfigType.Any || configType == ConfigType.Slider)
{
Console.Info($"Saved {num2} slider values for {RaceDisplayValues.Keys.Count} races", LogLocation.ConsoleAndIngame);
}
if (configType == ConfigType.Any || configType == ConfigType.DynamicBone)
{
Console.Info($"Saved {num} dbone values for {DynamicBoneValues.Keys.Count} parts", LogLocation.ConsoleAndIngame);
}
}
else
{
Console.Info("Config is empty, disabling console.", LogLocation.ConsoleAndIngame);
if (IngameConsole)
{
IngameConsole = false;
}
}
}
}
public enum ConfigType
{
Any,
DynamicBone,
Slider
}
public static class Commands
{
[HarmonyPatch(typeof(ChatBehaviour), "OnStartAuthority")]
public static class AwakePatch
{
[HarmonyPostfix]
public static void OnStartAuthority_Postfix(ChatBehaviour __instance)
{
if ((Object)(object)__instance._player != (Object)(object)Player._mainPlayer)
{
return;
}
chat = __instance;
baseEmotes = new Dictionary<string, EmoteCommand>();
commands = new Dictionary<string, CommandInfo>();
customEmotes = new Dictionary<string, EmoteInfo>();
if ((Object)(object)__instance._scriptableEmoteList == (Object)null || __instance._scriptableEmoteList._emoteCommandList == null)
{
Console.Error("Couldn't read Atlyss' emote list.");
return;
}
__instance._scriptableEmoteList._emoteCommandList.ToList().ForEach(delegate(EmoteCommand e)
{
baseEmotes.Add(e._emoteChatCommand, e);
});
AppearancePlus.OnChatInitialized.Invoke();
}
}
[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
public static class AddCommandsPatch
{
[HarmonyPrefix]
public static bool Send_ChatMessage_Prefix(ChatBehaviour __instance, string _message)
{
_message = _message.ToLower();
bool num = _message.StartsWith("/");
string pattern = "(?i)\\b(true|false)\\b|[-+]?\\b\\d+(\\.\\d+)?\\b|[^\\w\\s]";
string input = Regex.Replace(_message, pattern, " ");
input = Regex.Replace(input, "\\s+", " ").Trim();
if (num && commands.TryGetValue(input, out var value))
{
string[] array = _message.Replace("/" + value.Name, "").Split(" ", StringSplitOptions.RemoveEmptyEntries);
int num2 = ((value.Action == null) ? ((value.Action1 != null) ? 1 : ((value.Action2 != null) ? 2 : (-1))) : 0);
if (num2 == -1)
{
Console.Error("Command " + value.Name + " has not been configured correctly.", LogLocation.ConsoleAndIngame);
return false;
}
if (num2 != array.Length)
{
Console.Error($"Command {value.Name} was called with {array.Length} parameter(s) instead of {num2}.", LogLocation.ConsoleAndIngame);
return false;
}
bool flag = false;
switch (num2)
{
case 0:
flag = value.Action();
break;
case 1:
flag = value.Action1(array[0]);
break;
case 2:
flag = value.Action2(array[0], array[1]);
break;
}
if (flag && !string.IsNullOrEmpty(value.Response))
{
SendMessage(value.Response);
}
chat._lastMessage = _message;
__instance._chatInput.text = "";
return false;
}
return true;
}
}
private static ChatBehaviour chat;
private static Dictionary<string, CommandInfo> commands = new Dictionary<string, CommandInfo>();
private static Dictionary<string, EmoteCommand> baseEmotes = new Dictionary<string, EmoteCommand>();
private static Dictionary<string, EmoteInfo> customEmotes = new Dictionary<string, EmoteInfo>();
public static bool Add(CommandInfo command)
{
command.Name = command.Name.ToLower().TrimStart('/').Trim();
if (CommandExists(command.Name))
{
Console.Error("Cannot add /" + command.Name + " as it already exists or an error has occured..");
return false;
}
commands.Add(command.Name, command);
return true;
}
public static bool AddEmote(EmoteInfo emote)
{
try
{
if (emote.ChatCommand == null)
{
Console.Error("Emote has been added without a chat command.");
}
emote.ChatCommand = emote.ChatCommand.ToLower().TrimStart('/').Trim();
if (CommandExists(emote.ChatCommand))
{
Console.Error("Cannot add /" + emote.ChatCommand + " as it already exists or an error has occured.");
return false;
}
commands.Add(emote.ChatCommand, new CommandInfo(emote.ChatCommand, "Emote command to play " + emote.Name, emote.Message, () => PlayEmote(emote.ChatCommand)));
customEmotes.Add(emote.ChatCommand, emote);
return true;
}
catch (Exception ex)
{
Console.Error("Cannot add emote: " + ex.Message + ". Check that you have initialized all fields.");
return false;
}
}
public static bool PlayEmote(string emoteCommand)
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)AppearancePlus.PlayerVisual == (Object)null)
{
Console.Error("Main Player Visual has not been found.");
return false;
}
if ((Object)(object)AppearancePlus.PlayerModel == (Object)null)
{
Console.Error("Main Player Race Model has not been found.");
return false;
}
if (!customEmotes.ContainsKey(emoteCommand))
{
Console.Error("Could not find custom emote " + emoteCommand + ".");
return false;
}
PlayerRaceModel playerModel = AppearancePlus.PlayerModel;
EmoteInfo emoteInfo = customEmotes[emoteCommand];
if (PlayableGraphManager.PlayAnimationClip(playerModel, emoteInfo.AnimationTag, emoteInfo.Loop))
{
playerModel.Set_MouthCondition(emoteInfo.MouthAnim, -1f);
playerModel.Set_EyeCondition(emoteInfo.EyeAnim, -1f);
return true;
}
return false;
}
public static bool CommandExists(string commandName)
{
if (commands == null)
{
Console.Error("Commands not initialized.");
return true;
}
if (baseEmotes == null)
{
Console.Error("Base emotes not initialized");
return true;
}
if (!commands.ContainsKey(commandName))
{
return baseEmotes.ContainsKey("/" + commandName);
}
return true;
}
public static void SendMessage(string message)
{
chat.New_ChatMessage("<color=#ea8e09>[A+] " + message + "</color>");
}
public static void PrintCommands()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Commands:");
foreach (KeyValuePair<string, CommandInfo> command in commands)
{
stringBuilder.AppendLine("\n" + command.Key + ": " + command.Value.Description);
}
SendMessage(stringBuilder.ToString());
}
public static bool CmdParseFloat(string input, out float value)
{
if (!float.TryParse(input, out value))
{
Console.Warning("Couldn't parse " + input + ". Use float value like 3 or 3.6", LogLocation.ConsoleAndIngame);
return false;
}
return true;
}
public static bool CmdParseBool(string input, out bool value)
{
if (!bool.TryParse(input, out value))
{
Console.Warning("Couldn't parse " + input + ". Use bool value like true or false.", LogLocation.ConsoleAndIngame);
return false;
}
return true;
}
}
public struct CommandInfo
{
public string Name;
public string Description;
public Func<bool> Action;
public Func<string, bool> Action1;
public Func<string, string, bool> Action2;
public string Response;
public CommandInfo(string chatCommand, string description, string response)
{
Action = null;
Action1 = null;
Action2 = null;
Name = chatCommand;
Description = description;
Response = response;
}
public CommandInfo(string chatCommand, string description, string response, Func<bool> action)
: this(chatCommand, description, response)
{
Action = action;
}
public CommandInfo(string chatCommand, string description, string response, Func<string, bool> action)
: this(chatCommand, description, response)
{
Action1 = action;
Response = response;
}
public CommandInfo(string chatCommand, string description, string response, Func<string, string, bool> action)
: this(chatCommand, description, response)
{
Action2 = action;
Response = response;
}
}
public struct EmoteInfo
{
public string Name;
public string ChatCommand;
public string AnimationTag;
public string Message;
public bool Loop;
public EyeCondition EyeAnim;
public MouthCondition MouthAnim;
public EmoteInfo(string name, string chatCommand, string animationTag, string message, bool loop)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
EyeAnim = (EyeCondition)0;
MouthAnim = (MouthCondition)0;
Name = name;
ChatCommand = chatCommand;
AnimationTag = animationTag;
Message = message;
Loop = loop;
}
}
public static class Console
{
public struct LogInfo
{
public LogLevel Type;
public string Text;
public float Timestamp;
public LogInfo(LogLevel level, string message)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
Timestamp = Time.realtimeSinceStartup;
Type = level;
Text = message;
}
}
[HarmonyPatch(typeof(SettingsManager), "OnGUI")]
public static class SettingsManagerPatch
{
[HarmonyPostfix]
private static void OnGUIPatch(SettingsManager __instance)
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
if (_logs.Count == 0)
{
return;
}
GUIStyle label = GUI.skin.label;
label.richText = true;
label.fontSize = 30;
float num = 800f;
float num2 = 45f;
int count = _logs.Count;
Vector2 val = default(Vector2);
((Vector2)(ref val))..ctor((float)Screen.width * 0.01f, (float)Screen.height * 0.5f);
Color color = GUI.color;
GUI.Box(new Rect(val.x - 20f, val.y - (float)(count - 1) * num2 - 20f, num + 40f, num2 * (float)_logs.Count + 40f), "");
for (int num3 = _logs.Count - 1; num3 >= 0; num3--)
{
Color color2 = _logColors[_logs[num3].Type];
float num4 = Time.realtimeSinceStartup - _logs[num3].Timestamp;
float num5 = _timeout[_logs[num3].Type];
if (num4 <= 0.33f)
{
color2.a = num4 * 3f;
}
else
{
color2.a = Mathf.Clamp(num5 - num4, 0f, 0.33f) * 3f;
}
GUI.color = color2;
GUI.Label(new Rect(val.x, val.y - (float)(count - num3 - 1) * num2, num, num2), _logs[num3].Text, label);
}
GUI.color = color;
}
}
private static List<LogInfo> _logs = new List<LogInfo>();
private const int MaxLogs = 10;
private static ManualLogSource _logger;
private static Dictionary<LogLevel, Color> _logColors = new Dictionary<LogLevel, Color>
{
[(LogLevel)32] = new Color(0.929f, 0.929f, 0.929f),
[(LogLevel)16] = new Color(1f, 0.606f, 0.094f),
[(LogLevel)4] = new Color(0.961f, 0.859f, 0.208f),
[(LogLevel)2] = new Color(0.969f, 0.298f, 0.035f)
};
private static Dictionary<LogLevel, float> _timeout = new Dictionary<LogLevel, float>
{
{
(LogLevel)32,
10f
},
{
(LogLevel)16,
15f
},
{
(LogLevel)4,
15f
},
{
(LogLevel)2,
20f
}
};
private static float _lastLogTimestamp;
private static bool IngameConsole => Configuration.IngameConsole;
public static void Initialize(ManualLogSource logger)
{
_logger = logger;
}
public static void Update()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
while (num < _logs.Count)
{
LogInfo logInfo = _logs[num];
if (Time.realtimeSinceStartup - logInfo.Timestamp > _timeout[logInfo.Type])
{
_logs.RemoveAt(num);
}
else
{
num++;
}
}
}
public static bool ToggleConsole(string text)
{
if (!bool.TryParse(text, out var result))
{
Error("Couldn't parse parameter. Use true or false.");
return false;
}
Configuration.IngameConsole = result;
Commands.SendMessage((result ? "Enabled" : "Disabled") + " ingame console.");
return true;
}
public static void Log(LogLevel level, string message, LogLocation location = LogLocation.Console)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
if (location == LogLocation.Console || location == LogLocation.ConsoleAndIngame)
{
_logger.Log(level, (object)(message ?? ""));
}
if ((location == LogLocation.Ingame || location == LogLocation.ConsoleAndIngame) && Configuration.IngameConsole)
{
LogInfo item = new LogInfo(level, message);
_logs.Add(item);
_lastLogTimestamp = item.Timestamp;
if (_logs.Count > 10)
{
_logs.RemoveAt(0);
}
}
}
public static void Debug(string message, LogLocation location = LogLocation.Console)
{
Log((LogLevel)32, message, location);
}
public static void Info(string message, LogLocation location = LogLocation.Console)
{
Log((LogLevel)16, message, location);
}
public static void Warning(string message, LogLocation location = LogLocation.Console)
{
Log((LogLevel)4, message, location);
}
public static void Error(string message, LogLocation location = LogLocation.Console)
{
Log((LogLevel)2, message, location);
}
}
public enum LogLocation
{
Console,
Ingame,
ConsoleAndIngame
}
public static class DBonesLoader
{
public static int SetValues(PlayerRaceModel __instance)
{
int num = 0;
int num2 = 0;
int num3 = 0;
List<DynamicBone> list = ((Component)__instance).GetComponentsInChildren<DynamicBone>().ToList();
foreach (DynamicBone item in list)
{
StringBuilder stringBuilder = new StringBuilder(((Object)item).name);
stringBuilder.Replace("Base", "");
stringBuilder.Replace("base", "");
stringBuilder.Replace(" ", "");
stringBuilder.Replace(".l", "");
stringBuilder.Replace(".r", "");
string text = stringBuilder.ToString().ToLower();
if (!Configuration.DynamicBoneValues.ContainsKey(text))
{
continue;
}
foreach (var item2 in Configuration.DynamicBoneValues[text])
{
switch (item2.Item1)
{
case "damping":
item.m_Damping = item2.Item2;
break;
case "elasticity":
item.m_Elasticity = item2.Item2;
break;
case "stiffness":
item.m_Stiffness = item2.Item2;
break;
case "inert":
item.m_Inert = item2.Item2;
break;
default:
Console.Error("Could not apply property " + item2.Item1 + " to " + text + ".", LogLocation.ConsoleAndIngame);
num3++;
continue;
}
num2++;
}
num++;
}
list.ForEach(delegate(DynamicBone d)
{
d.UpdateParameters();
});
if (num3 > 0)
{
Console.Info($"Loaded {num2} properties in {num} parts.", LogLocation.ConsoleAndIngame);
Console.Info($"Failed to load {num3} properties.", LogLocation.ConsoleAndIngame);
Console.Warning("Check BepInEx console for more details.", LogLocation.Ingame);
}
return num;
}
public static void SetAll()
{
int num = 0;
int num2 = 0;
while (num2 < AppearancePlus.PlayerModels.Count)
{
PlayerRaceModel val = AppearancePlus.PlayerModels[num2];
if ((Object)(object)val != (Object)null)
{
num += SetValues(val);
num2++;
}
else
{
AppearancePlus.PlayerModels.RemoveAt(num2);
}
}
Console.Info($"Loaded properties in {num} parts.", LogLocation.ConsoleAndIngame);
}
public static bool PrintCurrentValues()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Printing current dynamic bone values:");
foreach (KeyValuePair<string, List<(string, float)>> dynamicBoneValue in Configuration.DynamicBoneValues)
{
try
{
stringBuilder.AppendLine("\n" + dynamicBoneValue.Key + ":");
foreach (var item in dynamicBoneValue.Value)
{
stringBuilder.AppendLine($" {item.Item1}:{item.Item2}");
}
}
catch (Exception ex)
{
Console.Error(ex.ToString(), LogLocation.ConsoleAndIngame);
return false;
}
}
Commands.SendMessage(stringBuilder.ToString());
return true;
}
}
public static class SliderLoader
{
[HarmonyPatch(typeof(ScriptablePlayerRace), "Init_ParamsCheck")]
public static class ScriptablePlayerRaceInitPatch
{
[HarmonyPrefix]
public static bool Init_ParamsCheck_Prefix(ScriptablePlayerRace __instance, ref PlayerAppearance_Profile __result, PlayerAppearance_Profile _aP)
{
__result = _aP;
return false;
}
}
public static void SetValues()
{
int num = 0;
int num2 = 0;
int num3 = 0;
ScriptablePlayerRace[] scriptablePlayerRaces = AppearancePlus.ScriptablePlayerRaces;
Dictionary<string, List<(string, (float, float))>> raceDisplayValues = Configuration.RaceDisplayValues;
ScriptablePlayerRace[] array = scriptablePlayerRaces;
foreach (ScriptablePlayerRace val in array)
{
string text = val._raceName.ToLower();
if (raceDisplayValues.ContainsKey(text))
{
num++;
num2 += ModifyCharacterParams(ref val._raceDisplayParams, text);
}
}
if (num3 > 0)
{
Console.Info($"Loaded {num2} properties in {num} races.", LogLocation.ConsoleAndIngame);
Console.Error($"Failed to load {num3} properties.", LogLocation.ConsoleAndIngame);
Console.Warning("Check BepInEx console for more details.", LogLocation.Ingame);
}
else
{
Console.Info($"Loaded all {num2} properties in {num} races.", LogLocation.ConsoleAndIngame);
}
}
public static int ModifyCharacterParams(ref CharacterParamsGroup currentProperties, string raceName)
{
//IL_022e: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_0255: Unknown result type (might be due to invalid IL or missing references)
//IL_025a: Unknown result type (might be due to invalid IL or missing references)
//IL_027c: Unknown result type (might be due to invalid IL or missing references)
//IL_0281: Unknown result type (might be due to invalid IL or missing references)
//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
//IL_030f: Unknown result type (might be due to invalid IL or missing references)
//IL_0314: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
foreach (var item in Configuration.RaceDisplayValues[raceName])
{
switch (item.Item1)
{
case "height":
currentProperties._heightRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "width":
currentProperties._widthRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "chest":
currentProperties._boobRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "arms":
currentProperties._armRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "belly":
currentProperties._bellyRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "bottom":
currentProperties._bottomRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "torso":
currentProperties._torsoRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "head":
currentProperties._headWidthRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "muzzle":
currentProperties._headModRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
case "voice":
currentProperties._pitchRange = new Vector2(item.Item2.Item1, item.Item2.Item2);
break;
default:
continue;
}
num++;
}
return num;
}
public static bool PrintCurrentValues()
{
StringBuilder stringBuilder = new StringBuilder();
PlayerRaceModel playerModel = AppearancePlus.PlayerModel;
if ((Object)(object)playerModel == (Object)null)
{
Commands.SendMessage("Couldn't find player!");
return false;
}
stringBuilder.AppendLine("Printing current slider values:");
stringBuilder.AppendLine($"\nVoice: {playerModel._muzzleWeight}");
stringBuilder.AppendLine($"\nHead: {playerModel._headWidth}");
stringBuilder.AppendLine($"\nMuzzle: {playerModel._muzzleWeight}");
stringBuilder.AppendLine($"\nArms: {playerModel._armWeight}");
stringBuilder.AppendLine($"\nChest: {playerModel._boobWeight}");
stringBuilder.AppendLine($"\nTorso: {playerModel._torsoWeight}");
stringBuilder.AppendLine($"\nBelly: {playerModel._bellyWeight}");
stringBuilder.AppendLine($"\nBottom: {playerModel._bottomWeight}");
stringBuilder.AppendLine($"\nHeight: {playerModel._heightWeight}");
stringBuilder.AppendLine($"\nWidth: {playerModel._widthWeight}");
Commands.SendMessage(stringBuilder.ToString());
return true;
}
public static bool SizeCommand(string parameter)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
if (!float.TryParse(parameter, out var result))
{
Console.Warning("Couldn't parse parameter. Use float value like 3 or 3.6", LogLocation.ConsoleAndIngame);
return false;
}
PlayerVisual playerVisual = AppearancePlus.PlayerVisual;
if ((Object)(object)playerVisual == (Object)null)
{
Console.Warning("Couldn't find player's visual.", LogLocation.ConsoleAndIngame);
return false;
}
PlayerRaceModel playerModel = AppearancePlus.PlayerModel;
if ((Object)(object)playerModel == (Object)null)
{
Console.Warning("Couldn't find player's race model.", LogLocation.ConsoleAndIngame);
return false;
}
float num = result / playerModel._heightWeight;
float widthWeight = playerModel._widthWeight * num;
CharacterParamsGroup raceDisplayParams = playerModel._scriptablePlayerRace._raceDisplayParams;
PlayerAppearanceStruct playerAppearanceStruct = playerVisual._playerAppearanceStruct;
playerAppearanceStruct._heightWeight = result;
if (playerAppearanceStruct._heightWeight > raceDisplayParams._heightRange.y)
{
raceDisplayParams._heightRange.y = playerAppearanceStruct._heightWeight;
}
else if (playerAppearanceStruct._heightWeight < raceDisplayParams._heightRange.x)
{
raceDisplayParams._heightRange.x = playerAppearanceStruct._heightWeight;
}
playerAppearanceStruct._widthWeight = widthWeight;
if (playerAppearanceStruct._widthWeight > raceDisplayParams._widthRange.y)
{
raceDisplayParams._widthRange.y = playerAppearanceStruct._widthWeight;
}
else if (playerAppearanceStruct._widthWeight < raceDisplayParams._widthRange.x)
{
raceDisplayParams._widthRange.x = playerAppearanceStruct._widthWeight;
}
playerModel._heightWeight = result;
playerModel._widthWeight = widthWeight;
playerVisual._playerAppearanceStruct = playerAppearanceStruct;
playerVisual.Cmd_SendNew_PlayerAppearanceStruct(playerAppearanceStruct);
playerVisual.Apply_NetworkedCharacterDisplay();
Commands.SendMessage($"Updated height to {playerModel._heightWeight} and width to {playerModel._widthWeight} for main player.");
return true;
}
}
public static class TextureLoader
{
internal static Dictionary<string, Texture2D> NonReplacedTextures = new Dictionary<string, Texture2D>();
private static Dictionary<string, Texture> OriginalTextures = new Dictionary<string, Texture>();
private static Dictionary<string, Dictionary<string, Texture2D>> TextureCache = new Dictionary<string, Dictionary<string, Texture2D>>();
private static Dictionary<string, Texture2D> CustomTextureCache = new Dictionary<string, Texture2D>();
public static void LoadTextures(string texturefolder)
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
int num = 0;
int num2 = 0;
bool flag = texturefolder.Contains("CustomTextures");
if (!flag && !TextureCache.ContainsKey(texturefolder))
{
TextureCache.Add(texturefolder, new Dictionary<string, Texture2D>());
}
try
{
string[] files = Directory.GetFiles(texturefolder, "*.png", SearchOption.AllDirectories);
foreach (string text in files)
{
try
{
if (text.Contains("IgnoredFiles"))
{
continue;
}
byte[] array = File.ReadAllBytes(text);
Texture2D val = new Texture2D(4, 4, (TextureFormat)4, false);
((Texture)val).anisoLevel = 16;
if (ImageConversion.LoadImage(val, array))
{
((Object)val).name = Path.GetFileNameWithoutExtension(text);
if (flag)
{
SetSingleTextureFilteringMode(val);
CustomTextureCache[((Object)val).name] = val;
num2++;
continue;
}
if (TextureCache[texturefolder].ContainsKey(((Object)val).name))
{
Console.Warning(((Object)val).name + " is already in use. Swapping.");
}
TextureCache[texturefolder][((Object)val).name] = val;
}
else
{
Console.Error("Failed to load texture: " + text);
}
}
catch (Exception ex)
{
Console.Error("Error loading texture file '" + text + "': " + ex.Message);
}
}
}
catch (Exception ex2)
{
Console.Error("Error loading textures: " + ex2.Message);
}
if (flag && num2 > 0)
{
Console.Info($"Loaded {num2} custom textures successfully!", LogLocation.ConsoleAndIngame);
}
else if (num > 0)
{
Console.Info($"Loaded {num2} textures successfully!", LogLocation.ConsoleAndIngame);
}
}
private static void SetCustomTexturesFilteringMod()
{
if (CustomTextureCache.Count == 0)
{
return;
}
foreach (Texture2D value in CustomTextureCache.Values)
{
if ((Object)(object)value != (Object)null)
{
SetSingleTextureFilteringMode(value);
}
else
{
Console.Warning("Null texture found in PreloadedTextures.");
}
}
}
private static void SetSingleTextureFilteringMode(Texture2D texture)
{
if (!((Texture)texture).isReadable)
{
Console.Warning("Texture '" + ((Object)texture).name + "' is not readable. Skipping.");
return;
}
if ((Object)(object)SettingsManager._current == (Object)null || SettingsManager._current._settingsProfile == null)
{
Console.Error("SettingsManager or its profile is null. Cannot set texture filtering mode.");
return;
}
switch (SettingsManager._current._settingsProfile._textureFilterSetting)
{
case 0:
((Texture)texture).anisoLevel = 16;
((Texture)texture).filterMode = (FilterMode)1;
break;
case 1:
((Texture)texture).filterMode = (FilterMode)0;
break;
default:
Console.Warning("Unsupported texture filter setting. Defaulting to Point.");
((Texture)texture).filterMode = (FilterMode)0;
break;
}
}
private static void SwapCustomTextures()
{
if (CustomTextureCache.Count == 0)
{
return;
}
NonReplacedTextures = new Dictionary<string, Texture2D>(CustomTextureCache);
int num = 0;
ScriptablePlayerRace[] scriptablePlayerRaces = AppearancePlus.ScriptablePlayerRaces;
foreach (ScriptablePlayerRace val in scriptablePlayerRaces)
{
string raceName = val._raceName;
SkinTextureGroup[] skinTextureGroups = val._skinTextureGroups;
foreach (SkinTextureGroup val2 in skinTextureGroups)
{
if (ReplaceTexture(ref val2._headTexture, "Head", raceName))
{
num++;
}
if (ReplaceTexture(ref val2._bodyTexture, "Body", raceName))
{
num++;
}
if (ReplaceTexture(ref val2._legTexture, "Leg", raceName))
{
num++;
}
if (ReplaceTexture(ref val2._tailTexture, "Tail", raceName))
{
num++;
}
if (ReplaceTexture(ref val2._earTexture, "Ear", raceName))
{
num++;
}
if (ReplaceTexture(ref val2._hairTexture, "Hair", raceName))
{
num++;
}
}
MouthTextureGroup[] mouthTextures = val._mouthTextures;
foreach (MouthTextureGroup val3 in mouthTextures)
{
if (ReplaceTexture(ref val3._open, "Open", "Mouth", raceName))
{
num++;
}
if (ReplaceTexture(ref val3._closed, "Closed", "Mouth", raceName))
{
num++;
}
}
EyeTextureGroup[] eyeTextures = val._eyeTextures;
foreach (EyeTextureGroup val4 in eyeTextures)
{
if (ReplaceTexture(ref val4._center, "Center", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._pissed, "Pissed", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._hurt, "Hurt", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._left, "Left", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._right, "Right", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._up, "Up", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._down, "Down", "Eye", raceName))
{
num++;
}
if (ReplaceTexture(ref val4._closed, "Closed", "Eye", raceName))
{
num++;
}
}
}
AppearancePlus.NetNPCs.RemoveAll((NetNPC npc) => (Object)(object)npc == (Object)null);
List<NetNPC> list = new List<NetNPC>(AppearancePlus.NetNPCs);
for (int k = 0; k < list.Count; k++)
{
num += ReplaceNPCTextures(list[k]);
}
if (NonReplacedTextures.Count > 0)
{
if (num > 0)
{
Console.Info($"Replaced {num} textures successfully!", LogLocation.ConsoleAndIngame);
}
Console.Warning($"Didn't find a match (in active entities) for {NonReplacedTextures.Count} textures.", LogLocation.ConsoleAndIngame);
Console.Warning("(This is normal for NPCs & Enemies)", LogLocation.ConsoleAndIngame);
Console.Warning("Check BepInEx console for more details.", LogLocation.Ingame);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine($"{NonReplacedTextures.Count} Non-Replaced Textures:");
foreach (KeyValuePair<string, Texture2D> nonReplacedTexture in NonReplacedTextures)
{
stringBuilder.AppendLine("- " + nonReplacedTexture.Key);
}
Console.Info(stringBuilder.ToString());
}
else if (num > 0)
{
Console.Info($"Replaced all textures in {num} instances successfully!", LogLocation.ConsoleAndIngame);
}
}
public static void DumpInfo()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Texture Info Dump:");
foreach (KeyValuePair<string, Texture> originalTexture in OriginalTextures)
{
stringBuilder.AppendLine($"\n {originalTexture.Key}: {originalTexture.Value.filterMode}|{originalTexture.Value.graphicsFormat}|{originalTexture.Value.anisoLevel}");
}
Console.Info(stringBuilder.ToString());
}
public static bool ReplaceTexture(ref Texture texture, params string[] keywords)
{
if ((Object)(object)texture == (Object)null)
{
Console.Warning(((Object)texture).name + " is null");
return false;
}
if (CustomTextureCache.TryGetValue(((Object)texture).name, out var value))
{
OriginalTextures.TryAdd(((Object)texture).name, texture);
texture = (Texture)(object)value;
NonReplacedTextures.Remove(((Object)texture).name);
return true;
}
if (OriginalTextures.TryGetValue(((Object)texture).name, out var value2))
{
texture = value2;
return false;
}
return false;
}
public static bool ReplaceRendererTexture(Renderer renderer, Texture2D customTexture = null)
{
if ((Object)(object)renderer == (Object)null)
{
return false;
}
if ((Object)(object)renderer.material == (Object)null)
{
return false;
}
if (!renderer.material.HasTexture("_MainTex") || (Object)(object)renderer.material.mainTexture == (Object)null)
{
return false;
}
Texture mainTexture = renderer.material.mainTexture;
if ((Object)(object)customTexture == (Object)null && !CustomTextureCache.TryGetValue(((Object)mainTexture).name, out customTexture))
{
if (OriginalTextures.TryGetValue(((Object)mainTexture).name, out var value))
{
renderer.material.mainTexture = value;
}
return false;
}
OriginalTextures.TryAdd(((Object)mainTexture).name, mainTexture);
renderer.material.mainTexture = (Texture)(object)customTexture;
NonReplacedTextures.Remove(((Object)mainTexture).name);
return true;
}
public static int ReplaceCreepTextures(CreepBehavior creep)
{
if (CustomTextureCache.Count == 0)
{
return 0;
}
int num = 0;
try
{
if ((Object)(object)creep == (Object)null)
{
Console.Warning("Creep instance is null.");
}
else
{
Renderer[] componentsInChildren = ((Component)creep).GetComponentsInChildren<Renderer>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
if (ReplaceRendererTexture(componentsInChildren[i]))
{
num++;
}
}
}
}
catch (Exception ex)
{
Console.Error("Error in OnNpcStart: " + ex.Message);
}
return num;
}
public static int ReplaceNPCTextures(NetNPC npc)
{
if (CustomTextureCache.Count == 0)
{
return 0;
}
int num = 0;
try
{
if ((Object)(object)npc == (Object)null)
{
Console.Warning("NetNPC instance is null.");
}
else
{
Renderer[] componentsInChildren = ((Component)npc).GetComponentsInChildren<Renderer>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
if (ReplaceRendererTexture(componentsInChildren[i]))
{
num++;
}
}
}
}
catch (Exception ex)
{
Console.Error("Error in OnNpcStart: " + ex.Message);
}
return num;
}
public static void ReplaceTextureAnim(TextureChangeAnimEvent textureAnim)
{
if (CustomTextureCache.Count == 0)
{
return;
}
int num = 0;
try
{
if ((Object)(object)textureAnim == (Object)null)
{
Console.Warning("Texture Anim instance is null.");
return;
}
TextureChangeAnimStruct[] array = (TextureChangeAnimStruct[])textureAnim._textureStructs.Clone();
for (int i = 0; i < array.Length; i++)
{
Texture value2;
if (CustomTextureCache.TryGetValue(((Object)array[i]._texture).name, out var value))
{
OriginalTextures.TryAdd(((Object)array[i]._texture).name, array[i]._texture);
array[i]._texture = (Texture)(object)value;
num++;
}
else if (OriginalTextures.TryGetValue(((Object)array[i]._texture).name, out value2))
{
array[i]._texture = value2;
}
}
textureAnim._textureStructs = array;
}
catch (Exception ex)
{
Console.Error("Error in CreepBehaviour Start: " + ex.Message);
}
}
public static void ApplyCustomTextures()
{
SetCustomTexturesFilteringMod();
SwapCustomTextures();
}
public static void ReloadAllTextures()
{
CustomTextureCache.Clear();
foreach (string key in TextureCache.Keys)
{
LoadTextures(key);
}
if (PathUtils.GetDirectory(AppearancePlus.DllPath, "CustomTextures", out var result))
{
LoadTextures(result);
ApplyCustomTextures();
}
}
}
}
namespace AppearancePlus.Utils
{
internal class ComponentDump
{
public static void DumpComponentToFile(Component targetComponent)
{
if ((Object)(object)targetComponent == (Object)null)
{
Debug.LogWarning((object)"Target component is not set.");
return;
}
string text = Path.Combine(Paths.PluginPath, "Logs");
string path = SanitizeFileName(((Object)targetComponent).name + ".txt");
string text2 = Path.Combine(text, path);
if (!Directory.Exists(text))
{
Directory.CreateDirectory(text);
}
try
{
File.WriteAllText(text2, DumpComponent(targetComponent));
Debug.Log((object)("Component data dumped to " + text2));
}
catch (Exception ex)
{
Debug.LogError((object)("Failed to dump component data: " + ex.Message));
}
}
private static string SanitizeFileName(string fileName)
{
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
foreach (char oldChar in invalidFileNameChars)
{
fileName = fileName.Replace(oldChar, '_');
}
return fileName;
}
private static string DumpComponent(Component component)
{
Type type = ((object)component).GetType();
string text = "Component Type: " + type.Name + "\n\n";
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (FieldInfo fieldInfo in fields)
{
text += $"{fieldInfo.Name}: {fieldInfo.GetValue(component)}\n";
}
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo propertyInfo in properties)
{
if (propertyInfo.CanRead)
{
try
{
text += $"{propertyInfo.Name}: {propertyInfo.GetValue(component)}\n";
}
catch
{
text = text + propertyInfo.Name + ": [Error]\n";
}
}
}
return text;
}
}
public class PathUtils
{
public static bool GetDirectory(string path, string searchPattern, out string result)
{
result = Path.Combine(path, searchPattern);
if (Directory.Exists(result))
{
return true;
}
result = "";
string[] directories = Directory.GetDirectories(path, searchPattern, SearchOption.AllDirectories);
if (directories.Length == 0)
{
Console.Warning(searchPattern + " folder at " + path + " not found.", LogLocation.ConsoleAndIngame);
return false;
}
if (directories.Length > 1)
{
string[] directories2 = Directory.GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
if (directories2.Length == 0)
{
result = directories.First();
}
else
{
result = directories2.First();
}
Console.Warning("Multiple " + searchPattern + " folder folders found. Using " + result + ".", LogLocation.ConsoleAndIngame);
}
if (Utility.IsNullOrWhiteSpace(result))
{
result = directories.First();
}
return true;
}
}
}
namespace AppearancePlus.AssetBundles
{
internal class AssetBundleLoader
{
private static readonly ManualLogSource Logger;
public static readonly List<AssetBundle> LoadedBundles;
static AssetBundleLoader()
{
LoadedBundles = new List<AssetBundle>();
Logger = Logger.CreateLogSource("AtlyssAnimationManager");
}
public static void LoadAssetBundles(string assetBundlesFolder, string extension)
{
try
{
string[] files = Directory.GetFiles(assetBundlesFolder, "*." + extension);
Logger.LogInfo((object)$"Found {files.Length} AssetBundle(s) in {assetBundlesFolder}");
string[] array = files;
foreach (string text in array)
{
AssetBundle val = AssetBundle.LoadFromFile(text);
if ((Object)(object)val != (Object)null)
{
LoadedBundles.Add(val);
Console.Warning("Successfully loaded AssetBundle: " + Path.GetFileName(text));
}
else
{
Logger.LogError((object)("Failed to load AssetBundle: " + Path.GetFileName(text)));
}
}
Console.Info($"Loaded {LoadedBundles.Count} AssetBundles");
}
catch (Exception ex)
{
Logger.LogError((object)("Error loading AssetBundles: " + ex.Message + "\n" + ex.StackTrace));
}
}
public static void UnloadAllAssetBundles(bool unloadAllLoadedObjects = false)
{
foreach (AssetBundle loadedBundle in LoadedBundles)
{
Logger.LogInfo((object)$"Unloading AssetBundle: {((Object)loadedBundle).name}, UnloadAllObjects={unloadAllLoadedObjects}");
loadedBundle.Unload(unloadAllLoadedObjects);
}
LoadedBundles.Clear();
}
}
}
namespace AppearancePlus.Animation
{
internal class AnimationLoaderNpcPatch
{
[HarmonyPatch(typeof(NetNPC), "Start")]
public static class NetNPCStartPatch
{
[HarmonyPostfix]
public static void Postfix(NetNPC __instance)
{
}
}
}
internal class AnimationLoaderPlayerPatch
{
[HarmonyPatch(typeof(PlayerRaceModel), "Awake")]
public static class PlayerRaceModelAwakePatch
{
[HarmonyPostfix]
public static void Awake_Postfix(PlayerRaceModel __instance)
{
}
}
}
internal class AnimationLoader
{
private static readonly ManualLogSource Logger;
public static readonly List<AnimationClip> LoadedAnimationClips;
static AnimationLoader()
{
LoadedAnimationClips = new List<AnimationClip>();
Logger = Logger.CreateLogSource("AtlyssAnimationManager");
}
public static void LoadAllAnimationClips()
{
if (AssetBundleLoader.LoadedBundles.Count == 0)
{
Logger.LogWarning((object)"No AssetBundles are currently loaded. Ensure bundles are loaded before calling this method.");
return;
}
Logger.LogInfo((object)$"Attempting to load AnimationClips from {AssetBundleLoader.LoadedBundles.Count} AssetBundles.");
foreach (AssetBundle loadedBundle in AssetBundleLoader.LoadedBundles)
{
GetAllAnimationsFromBundle(loadedBundle);
}
Logger.LogInfo((object)$"Total loaded AnimationClips: {LoadedAnimationClips.Count}");
}
public static List<AnimationClip> GetAllAnimationsFromBundle(AssetBundle bundle)
{
List<AnimationClip> list = new List<AnimationClip>();
try
{
string[] allAssetNames = bundle.GetAllAssetNames();
foreach (string text in allAssetNames)
{
Object val = bundle.LoadAsset(text);
AnimationClip clip = (AnimationClip)(object)((val is AnimationClip) ? val : null);
if (clip != null)
{
if (!LoadedAnimationClips.Exists((AnimationClip c) => ((Object)c).name == ((Object)clip).name))
{
LoadedAnimationClips.Add(clip);
list.Add(clip);
Logger.LogInfo((object)("Loaded AnimationClip: " + ((Object)clip).name + " from AssetBundle: " + ((Object)bundle).name));
}
else
{
Logger.LogDebug((object)("Duplicate AnimationClip skipped: " + ((Object)clip).name));
}
}
}
}
catch (Exception ex)
{
Logger.LogError((object)("Error extracting AnimationClips from AssetBundle " + ((Object)bundle).name + ": " + ex.Message + "\n" + ex.StackTrace));
}
return list;
}
public static List<AnimationClip> GetLoadedAnimationClips()
{
return new List<AnimationClip>(LoadedAnimationClips);
}
}
internal class PlayableGraphManager
{
public static Dictionary<Animator, PlayableGraph> CharacterPlayableGraphs = new Dictionary<Animator, PlayableGraph>();
private static Dictionary<string, AnimationClipPlayable> PlayableClips = new Dictionary<string, AnimationClipPlayable>();
public static void PreloadPlayables(PlayableGraph graph)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
Console.Info("Preloading AnimationClipPlayables...");
foreach (AnimationClip loadedAnimationClip in AnimationLoader.GetLoadedAnimationClips())
{
if (!PlayableClips.ContainsKey(((Object)loadedAnimationClip).name))
{
AnimationClipPlayable value = AnimationClipPlayable.Create(graph, loadedAnimationClip);
PlayableClips.Add(((Object)loadedAnimationClip).name, value);
Console.Info("Preloaded clip: " + ((Object)loadedAnimationClip).name);
}
}
}
public static void InitCharacterAnimations(PlayerRaceModel character)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || (Object)(object)character._raceAnimator == (Object)null)
{
Console.Error("Character or Animator is null. Cannot add character.");
return;
}
Console.Info("AddCharacter called for " + ((Object)character).name);
PlayableGraph val = PlayableGraph.Create(((Object)character).name + "_PlayableGraph");
try
{
AnimationPlayableOutput.Create(val, "AnimationOutput", character._raceAnimator);
Console.Info("AnimationPlayableOutput created for " + ((Object)character).name + ".");
if (AnimationLoader.GetLoadedAnimationClips().Count > 0)
{
Console.Info($"Loaded animation clips: {AnimationLoader.GetLoadedAnimationClips().Count}");
Console.Info("Preloading playables for " + ((Object)character).name + "...");
PreloadPlayables(val);
CharacterPlayableGraphs.Add(character._raceAnimator, val);
Console.Info("PlayableGraph for " + ((Object)character).name + " added.");
((PlayableGraph)(ref val)).Play();
Console.Info("PlayableGraph for " + ((Object)character).name + " started.");
}
else
{
Console.Warning("No animation clips loaded. PlayableGraph for " + ((Object)character).name + " not initialized with playables.");
}
}
catch (Exception ex)
{
Console.Error("Error initializing PlayableGraph for " + ((Object)character).name + ": " + ex.Message);
}
}
public static void InitCharacterAnimations(NetNPC character)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || (Object)(object)character._animator == (Object)null)
{
Console.Error("Character or Animator is null. Cannot add character.");
return;
}
Console.Info("AddCharacter called for " + ((Object)character).name);
PlayableGraph val = PlayableGraph.Create(((Object)character).name + "_PlayableGraph");
try
{
AnimationPlayableOutput.Create(val, "AnimationOutput", character._animator);
Console.Info("AnimationPlayableOutput created for " + ((Object)character).name + ".");
if (AnimationLoader.GetLoadedAnimationClips().Count > 0)
{
Console.Info($"Loaded animation clips: {AnimationLoader.GetLoadedAnimationClips().Count}");
Console.Info("Preloading playables for " + ((Object)character).name + "...");
PreloadPlayables(val);
CharacterPlayableGraphs.Add(character._animator, val);
Console.Info("PlayableGraph for " + ((Object)character).name + " added.");
Console.Info("PlayableGraph for " + ((Object)character).name + " started.");
}
else
{
Console.Warning("No animation clips loaded. PlayableGraph for " + ((Object)character).name + " not initialized with playables.");
}
}
catch (Exception ex)
{
Console.Error("Error initializing PlayableGraph for " + ((Object)character).name + ": " + ex.Message);
}
}
public static bool PlayAnimationClip(PlayerRaceModel character, string clipName, bool loop)
{
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || (Object)(object)character._raceAnimator == (Object)null)
{
Console.Error("Character or Animator is null. Cannot play animation.");
return false;
}
if (!CharacterPlayableGraphs.TryGetValue(character._raceAnimator, out var value))
{
Console.Error("PlayableGraph for " + ((Object)character).name + " not found.");
return false;
}
if (!PlayableClips.TryGetValue(clipName, out var value2))
{
Console.Error("AnimationClipPlayable with name '" + clipName + "' not found.");
Console.Info("Available clips: " + string.Join(", ", PlayableClips.Keys));
return false;
}
try
{
((PlayableGraph)(ref value)).Play();
PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationClipPlayable>((AnimationPlayableOutput)((PlayableGraph)(ref value)).GetOutput(0), value2);
PlayableExtensions.SetTime<AnimationClipPlayable>(value2, 0.0);
((MonoBehaviour)character).StartCoroutine(MonitorAnimationPlayback(value, value2, loop));
Console.Info("Playing clip '" + clipName + "' on " + ((Object)character).name + ".");
return true;
}
catch (Exception ex)
{
Console.Error("Error playing clip '" + clipName + "' on " + ((Object)character).name + ": " + ex.Message);
}
return false;
}
public static bool PlayAnimationClip(NetNPC character, string clipName, bool loop)
{
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || (Object)(object)character._animator == (Object)null)
{
Console.Error("Character or Animator is null. Cannot play animation.");
return false;
}
if (!CharacterPlayableGraphs.TryGetValue(character._animator, out var value))
{
Console.Error("PlayableGraph for " + ((Object)character).name + " not found.");
return false;
}
if (!PlayableClips.TryGetValue(clipName, out var value2))
{
Console.Error("AnimationClipPlayable with name '" + clipName + "' not found.");
Console.Info("Available clips: " + string.Join(", ", PlayableClips.Keys));
return false;
}
try
{
((PlayableGraph)(ref value)).Play();
PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationClipPlayable>((AnimationPlayableOutput)((PlayableGraph)(ref value)).GetOutput(0), value2);
PlayableExtensions.SetTime<AnimationClipPlayable>(value2, 0.0);
((MonoBehaviour)character).StartCoroutine(MonitorAnimationPlayback(value, value2, loop));
Console.Info("Playing clip '" + clipName + "' on " + ((Object)character).name + ".");
return true;
}
catch (Exception ex)
{
Console.Error("Error playing clip '" + clipName + "' on " + ((Object)character).name + ": " + ex.Message);
}
return false;
}
private static IEnumerator MonitorAnimationPlayback(PlayableGraph graph, AnimationClipPlayable clipPlayable, bool loop)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
while (PlayableExtensions.GetTime<AnimationClipPlayable>(clipPlayable) < (double)((AnimationClipPlayable)(ref clipPlayable)).GetAnimationClip().length)
{
yield return null;
}
if (!loop)
{
((PlayableGraph)(ref graph)).Stop();
Console.Info("Animation finished and graph stopped.");
}
else
{
PlayableExtensions.SetTime<AnimationClipPlayable>(clipPlayable, 0.0);
}
}
public static void StopAnimationClip(PlayerRaceModel character)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
if (CharacterPlayableGraphs.TryGetValue(character._raceAnimator, out var value))
{
_ = (AnimationPlayableOutput)((PlayableGraph)(ref value)).GetOutput(0);
((PlayableGraph)(ref value)).Stop();
}
}
public static void StopAnimationClip(NetNPC character)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
if (CharacterPlayableGraphs.TryGetValue(character._animator, out var value))
{
_ = (AnimationPlayableOutput)((PlayableGraph)(ref value)).GetOutput(0);
((PlayableGraph)(ref value)).Stop();
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}