Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SemiKick v1.0.1
SemiKick.dll
Decompiled 4 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using KeybindLib.Classes; using Newtonsoft.Json; using Photon.Pun; using REPOLib.Modules; using REPOLib.Objects.Sdk; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("SemiKick")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SemiKick")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f6f7da04-f36c-4ac4-a3dc-28fbe347a753")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [Serializable] public class AnimationData { public float duration; public List<FrameData> frames; } [Serializable] public class FrameData { public float time; public Dictionary<string, BoneRotation> bones; } [Serializable] public struct BoneRotation { public float x; public float y; public float z; public float w; public Quaternion ToQuaternion() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(x, y, z, w); } } public struct RuntimeFrame { public float time; public Quaternion[] rotations; } public class KickAnimationPlayer : MonoBehaviour { private static readonly Dictionary<string, string> BoneMap = new Dictionary<string, string> { { "Bone", "ANIM BODY BOT" }, { "Bone.003", "ANIM HEAD BOT" }, { "Bone.004", "Player Spring Impulse - Leg Right" }, { "Bone.005", "Player Spring Impulse - Leg Left" }, { "Bone.006", "Player Spring Impulse - Arm Left" }, { "Bone.007", "Player Spring Impulse - Arm Right" } }; private Transform[] boneTransforms; private string[] blenderBoneNames; private Quaternion[] initialLocalRotations; private int rightLegBoneIndex = -1; private Vector3? stretchTargetWorldPos; private float currentStretchFactor = 1f; private RuntimeFrame[] runtimeFrames; private float totalDuration; private bool isReady; private bool isPlaying; [SerializeField] private float returnToRestDuration = 0.15f; private Coroutine returnToRestCoroutine; private RuntimeFrame currentFrameA; private RuntimeFrame currentFrameB; private float currentT; private bool hasFrameToApply; private bool _loggedFirstApply; private bool _loggedNullBoneWarning; private static string LoadTextFromEmbeddedResource(string resourceFileName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith(resourceFileName, StringComparison.OrdinalIgnoreCase)); if (text == null) { Debug.LogError((object)("[JSONAnimation] Embedded resource '" + resourceFileName + "' не найден. Доступные ресурсы: " + string.Join(", ", executingAssembly.GetManifestResourceNames()))); return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { Debug.LogError((object)("[JSONAnimation] GetManifestResourceStream вернул null для '" + text + "'.")); return null; } using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } public void Initialize(string jsonPath, Transform rigRoot) { Debug.Log((object)("[JSONAnimation] Initialize вызван: jsonPath=" + jsonPath + ", rigRoot=" + (((Object)(object)rigRoot != (Object)null) ? ((Object)rigRoot).name : "NULL"))); bool flag = File.Exists(jsonPath); Debug.Log((object)$"[JSONAnimation] Проверка файла анимации: fileExists={flag}, path={jsonPath}"); string text = (flag ? File.ReadAllText(jsonPath) : null); InitializeInternal(text, rigRoot, flag, "Файл kick_animation.json не найден по указанному пути. "); } public void InitializeFromJsonText(string jsonText, Transform rigRoot) { Debug.Log((object)string.Format("[JSONAnimation] Initialize (embedded) вызван: jsonText.Length={0}, rigRoot={1}", jsonText?.Length ?? (-1), ((Object)(object)rigRoot != (Object)null) ? ((Object)rigRoot).name : "NULL")); InitializeInternal(jsonText, rigRoot, !string.IsNullOrEmpty(jsonText), "JSON-текст из embedded resource пуст или не был найден (см. лог LoadTextFromEmbeddedResource выше). "); } public void InitializeFromEmbeddedResource(string resourceFileName, Transform rigRoot) { string jsonText = LoadTextFromEmbeddedResource(resourceFileName); InitializeFromJsonText(jsonText, rigRoot); } private void InitializeInternal(string text, Transform rigRoot, bool hasSource, string missingSourceReason) { //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = new List<Transform>(); List<string> list2 = new List<string>(); foreach (KeyValuePair<string, string> item in BoneMap) { Transform val = FindDeepChild(rigRoot, item.Value); if ((Object)(object)val != (Object)null) { list.Add(val); list2.Add(item.Key); Debug.Log((object)("[JSONAnimation] Привязана кость: blenderName=" + item.Key + " -> unityName='" + item.Value + "', path=" + GetHierarchyPath(val))); } else { Debug.LogWarning((object)("[JSONAnimation] НЕ найдена кость: blenderName=" + item.Key + ", ожидалось имя в Unity='" + item.Value + "' (FindDeepChild не нашёл такого объекта под " + (((Object)(object)rigRoot != (Object)null) ? ((Object)rigRoot).name : "NULL") + ").")); } } boneTransforms = list.ToArray(); blenderBoneNames = list2.ToArray(); int num = boneTransforms.Length; Debug.Log((object)$"[JSONAnimation] Итог поиска костей: найдено {num}/{BoneMap.Count}."); initialLocalRotations = (Quaternion[])(object)new Quaternion[num]; for (int i = 0; i < num; i++) { initialLocalRotations[i] = boneTransforms[i].localRotation; } rightLegBoneIndex = Array.IndexOf(blenderBoneNames, "Bone.004"); if (rightLegBoneIndex < 0) { Debug.LogWarning((object)"[JSONAnimation] Кость правой ноги (Bone.004 / 'Player Spring Impulse - Leg Right') не найдена в рантайм-иерархии — стретч ноги работать не будет для этого аватара."); } if (hasSource && num > 0) { Debug.Log((object)$"[JSONAnimation] JSON получен, длина текста={text.Length} символов. Десериализую..."); AnimationData animationData = JsonConvert.DeserializeObject<AnimationData>(text); if (animationData == null) { Debug.LogError((object)"[JSONAnimation] JsonConvert.DeserializeObject вернул NULL — файл битый или не соответствует структуре AnimationData. Анимация не будет готова."); return; } if (animationData.frames == null || animationData.frames.Count == 0) { Debug.LogError((object)$"[JSONAnimation] rawData.frames пуст или NULL (duration={animationData.duration}). Анимация не будет готова."); return; } totalDuration = animationData.duration; runtimeFrames = new RuntimeFrame[animationData.frames.Count]; Debug.Log((object)$"[JSONAnimation] Десериализация ок: duration={totalDuration}, framesCount={animationData.frames.Count}. Пересобираю в RuntimeFrame..."); int num2 = 0; for (int j = 0; j < animationData.frames.Count; j++) { FrameData frameData = animationData.frames[j]; runtimeFrames[j].time = frameData.time; runtimeFrames[j].rotations = (Quaternion[])(object)new Quaternion[num]; for (int k = 0; k < num; k++) { string key = blenderBoneNames[k]; if (frameData.bones != null && frameData.bones.TryGetValue(key, out var value)) { runtimeFrames[j].rotations[k] = value.ToQuaternion(); continue; } runtimeFrames[j].rotations[k] = boneTransforms[k].localRotation; num2++; } } if (num2 > 0) { Debug.LogWarning((object)$"[JSONAnimation] В {num2} случаях (кадр x кость) в JSON не было данных для найденной кости — использован текущий localRotation как фоллбэк. Если это не задумано, проверьте имена костей в Blender-экспорте."); } isReady = true; Debug.Log((object)$"[JSONAnimation] Initialize завершён успешно: isReady=true, totalDuration={totalDuration}, framesCount={runtimeFrames.Length}, boneCount={num}."); } else { Debug.LogWarning((object)($"[JSONAnimation] Initialize НЕ завершился (isReady останется false): hasSource={hasSource}, actualBoneCount={num}. " + ((!hasSource) ? missingSourceReason : "") + ((num == 0) ? "Ни одна кость из BoneMap не найдена в rigRoot — проверьте иерархию/имена." : ""))); } } private static string GetHierarchyPath(Transform t) { if ((Object)(object)t == (Object)null) { return "NULL"; } string text = ((Object)t).name; Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private IEnumerator RunKick() { if (returnToRestCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(returnToRestCoroutine); returnToRestCoroutine = null; } isPlaying = true; float startTime = Time.time; int currentFrameIndex = 0; int frameCount = runtimeFrames.Length; int loggedFrameIndex = -1; object[] obj = new object[4] { startTime, totalDuration, frameCount, null }; Transform[] array = boneTransforms; obj[3] = ((array != null) ? array.Length : 0); Debug.Log((object)string.Format("[JSONAnimation] RunKick стартовал: startTime={0}, totalDuration={1}, frameCount={2}, boneCount={3}.", obj)); while (Time.time - startTime < totalDuration) { float num; for (num = Time.time - startTime; currentFrameIndex < frameCount - 1 && runtimeFrames[currentFrameIndex + 1].time <= num; currentFrameIndex++) { } if (currentFrameIndex != loggedFrameIndex) { Debug.Log((object)$"[JSONAnimation] RunKick: переход на кадр {currentFrameIndex}/{frameCount - 1} (time={runtimeFrames[currentFrameIndex].time}, elapsed={num:F3})."); loggedFrameIndex = currentFrameIndex; } currentFrameA = runtimeFrames[currentFrameIndex]; currentFrameB = runtimeFrames[Mathf.Min(currentFrameIndex + 1, frameCount - 1)]; currentT = Mathf.InverseLerp(currentFrameA.time, currentFrameB.time, num); hasFrameToApply = true; yield return null; } isPlaying = false; hasFrameToApply = false; stretchTargetWorldPos = null; currentStretchFactor = 1f; if (rightLegBoneIndex >= 0 && rightLegBoneIndex < boneTransforms.Length && (Object)(object)boneTransforms[rightLegBoneIndex] != (Object)null) { boneTransforms[rightLegBoneIndex].localScale = Vector3.one; } if (returnToRestCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(returnToRestCoroutine); } returnToRestCoroutine = ((MonoBehaviour)this).StartCoroutine(ReturnToRestPose()); Debug.Log((object)$"[JSONAnimation] RunKick завершён: реальная длительность={Time.time - startTime:F3} (ожидалось totalDuration={totalDuration}), запущен плавный возврат костей в стартовую позу за {returnToRestDuration:F3}с."); } private IEnumerator ReturnToRestPose() { if (initialLocalRotations == null || boneTransforms == null) { yield break; } int count = boneTransforms.Length; Quaternion[] fromRotations = (Quaternion[])(object)new Quaternion[count]; for (int i = 0; i < count; i++) { if ((Object)(object)boneTransforms[i] != (Object)null) { fromRotations[i] = boneTransforms[i].localRotation; } } if (returnToRestDuration <= 0f) { for (int j = 0; j < count; j++) { if ((Object)(object)boneTransforms[j] != (Object)null && j < initialLocalRotations.Length) { boneTransforms[j].localRotation = initialLocalRotations[j]; } } returnToRestCoroutine = null; yield break; } float elapsed = 0f; while (elapsed < returnToRestDuration) { elapsed += Time.deltaTime; float num = Mathf.Clamp01(elapsed / returnToRestDuration); for (int k = 0; k < count; k++) { if ((Object)(object)boneTransforms[k] != (Object)null && k < initialLocalRotations.Length) { boneTransforms[k].localRotation = Quaternion.Slerp(fromRotations[k], initialLocalRotations[k], num); } } yield return null; } for (int l = 0; l < count; l++) { if ((Object)(object)boneTransforms[l] != (Object)null && l < initialLocalRotations.Length) { boneTransforms[l].localRotation = initialLocalRotations[l]; } } returnToRestCoroutine = null; } private void LateUpdate() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (!hasFrameToApply) { _loggedFirstApply = false; return; } if (!_loggedFirstApply) { Debug.Log((object)$"[JSONAnimation] LateUpdate: начал применять ротации к {boneTransforms.Length} костям."); _loggedFirstApply = true; } for (int i = 0; i < boneTransforms.Length; i++) { if ((Object)(object)boneTransforms[i] == (Object)null) { if (!_loggedNullBoneWarning) { Debug.LogWarning((object)$"[JSONAnimation] LateUpdate: boneTransforms[{i}] == NULL (кость уничтожена/недоступна?), пропускаю. Дальнейшие такие предупреждения на этот проигрыш подавлены."); _loggedNullBoneWarning = true; } } else { boneTransforms[i].localRotation = Quaternion.Slerp(currentFrameA.rotations[i], currentFrameB.rotations[i], currentT); } } if (rightLegBoneIndex >= 0 && rightLegBoneIndex < boneTransforms.Length && (Object)(object)boneTransforms[rightLegBoneIndex] != (Object)null) { ApplyLegStretch(boneTransforms[rightLegBoneIndex]); } } private void ApplyLegStretch(Transform legBone) { //IL_006c: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) float num = 1f; if (stretchTargetWorldPos.HasValue) { float num2 = Vector3.Distance(legBone.position, stretchTargetWorldPos.Value); float num3 = 0.5f; if (num3 > 0f && num2 > num3) { num = Mathf.Clamp(num2 / num3, 1f, 1.8f); } } currentStretchFactor = Mathf.Lerp(currentStretchFactor, num, Time.deltaTime * 8f); Vector3 one = Vector3.one; one.y = currentStretchFactor; legBone.localScale = one; } private Transform FindDeepChild(Transform parent, string targetName) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (((Object)parent).name == targetName) { return parent; } foreach (Transform item in parent) { Transform parent2 = item; Transform val = FindDeepChild(parent2, targetName); if ((Object)(object)val != (Object)null) { return val; } } return null; } public void PlayKick(Vector3? targetWorldPoint = null) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) Debug.Log((object)string.Format("[JSONAnimation] PlayKick вызван: isReady={0}, isPlaying={1}, gameObject={2}, targetWorldPoint={3}.", isReady, isPlaying, ((Object)this).name, targetWorldPoint.HasValue ? ((object)targetWorldPoint.Value/*cast due to .constrained prefix*/).ToString() : "NULL")); if (!isReady) { Debug.LogWarning((object)"[JSONAnimation] PlayKick: isReady=false, анимация не запущена (Initialize не завершился успешно — см. логи выше)."); return; } if (isPlaying) { Debug.LogWarning((object)"[JSONAnimation] PlayKick: анимация уже проигрывается (isPlaying=true), повторный запуск пропущен."); return; } stretchTargetWorldPos = targetWorldPoint; currentStretchFactor = 1f; ((MonoBehaviour)this).StartCoroutine(RunKick()); } } namespace SemiKick; internal class EnemyKickReceiver : MonoBehaviour { private const float KickStunDuration = 1f; private Enemy _enemy; private EnemyRigidbody _enemyRigidbody; private EnemyStateStunned _stateStunned; private void Awake() { _enemy = ((Component)this).GetComponent<Enemy>(); _stateStunned = InternalAccessors.GetEnemyStateStunned(_enemy); _enemyRigidbody = (((Object)(object)((Component)this).transform.parent != (Object)null) ? ((Component)((Component)this).transform.parent).GetComponentInChildren<EnemyRigidbody>() : ((Component)this).GetComponentInChildren<EnemyRigidbody>()); if ((Object)(object)_enemyRigidbody == (Object)null) { SemiKick.LogWarning("[SemiKick] EnemyKickReceiver на " + ((Object)this).name + ": не нашёл EnemyRigidbody у сиблингов родителя."); } if ((Object)(object)_stateStunned == (Object)null) { SemiKick.LogWarning("[SemiKick] EnemyKickReceiver на " + ((Object)this).name + ": не нашёл StateStunned — нокбэк будет гаситься AI на следующем кадре."); } SemiKick.LogInfo($"[SemiKick] EnemyKickReceiver.Awake на {((Object)this).name}: enemyRigidbody={(Object)(object)_enemyRigidbody != (Object)null}, stateStunned={(Object)(object)_stateStunned != (Object)null}"); } public float GetMass() { if ((Object)(object)_enemyRigidbody == (Object)null) { SemiKick.LogWarning("[SemiKick] EnemyKickReceiver.GetMass на " + ((Object)this).name + ": _enemyRigidbody == null, возвращаю 0."); return 0f; } Rigidbody enemyRigidbody = InternalAccessors.GetEnemyRigidbody(_enemyRigidbody); float num = (((Object)(object)enemyRigidbody != (Object)null) ? enemyRigidbody.mass : 0f); SemiKick.LogInfo($"[SemiKick] EnemyKickReceiver.GetMass на {((Object)this).name}: rb={(Object)(object)enemyRigidbody != (Object)null}, mass={num}"); return num; } public void SendKick(Vector3 force) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) SemiKick.LogInfo($"[SemiKick] EnemyKickReceiver.SendKick на {((Object)this).name}: force={force}, magnitude={((Vector3)(ref force)).magnitude}, Multiplayer={GameManager.Multiplayer()}"); if (!GameManager.Multiplayer()) { ReceiveKickRPC(force); return; } PhotonView enemyPhotonView = InternalAccessors.GetEnemyPhotonView(_enemy); if ((Object)(object)enemyPhotonView == (Object)null) { SemiKick.LogWarning("[SemiKick] EnemyKickReceiver.SendKick на " + ((Object)this).name + ": photonView == null, RPC не отправлен."); return; } enemyPhotonView.RPC("ReceiveKickRPC", (RpcTarget)0, new object[1] { force }); } [PunRPC] public void ReceiveKickRPC(Vector3 force, PhotonMessageInfo _info = default(PhotonMessageInfo)) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) SemiKick.LogInfo($"[SemiKick] EnemyKickReceiver.ReceiveKickRPC на {((Object)this).name}: force={force}"); if ((Object)(object)_enemyRigidbody == (Object)null) { SemiKick.LogWarning("[SemiKick] EnemyKickReceiver.ReceiveKickRPC на " + ((Object)this).name + ": _enemyRigidbody == null, импульс не применён."); return; } EnemyStateStunned stateStunned = _stateStunned; if (stateStunned != null) { stateStunned.Set(1f); } _enemyRigidbody.FreezeForces(force, Vector3.zero); } } [HarmonyPatch(typeof(Enemy), "Awake")] internal static class EnemyKickReceiverPatch { [HarmonyPostfix] private static void Postfix(Enemy __instance) { if (!((Object)(object)((Component)__instance).GetComponent<EnemyKickReceiver>() != (Object)null)) { ((Component)__instance).gameObject.AddComponent<EnemyKickReceiver>(); } } } public class KickAnimHandler : MonoBehaviour { private KickAnimationPlayer _animPlayer; private PhotonView _photonView; private PlayerAvatar _avatar; private bool _isLocal; private PlayerController pc; public PlayerAvatar Avatar => _avatar; public int KickLevel { get; private set; } public void SetKickLevel(int level) { SemiKick.LogInfo($"[SemiKick] KickAnimHandler.SetKickLevel: {(((Object)(object)_avatar != (Object)null) ? ((Object)_avatar).name : ((Object)this).name)} -> level={level} (было {KickLevel})."); KickLevel = level; } public void Initialize(KickAnimationPlayer animPlayer, PlayerAvatar avatar) { GameObject val = GameObject.Find("Controller"); if ((Object)(object)val != (Object)null) { pc = val.GetComponent<PlayerController>(); } if ((Object)(object)pc == (Object)null) { SemiKick.LogWarning("[KickAnimHandler] PlayerController не найден на сцене!"); } _animPlayer = animPlayer; _avatar = avatar; SemiKick.LogInfo("[SemiKick] KickAnimHandler.Initialize вызван, avatar=" + (((Object)(object)avatar != (Object)null) ? ((Object)avatar).name : "NULL")); SemiKick.LogInfo("[JSONAnimation] KickAnimHandler.Initialize: animPlayer передан как " + (((Object)(object)animPlayer != (Object)null) ? "не NULL" : "NULL") + "."); if ((Object)(object)avatar == (Object)null) { SemiKick.LogError("[SemiKick] KickAnimHandler.Initialize: avatar передана как NULL!"); return; } _photonView = avatar.photonView ?? ((Component)avatar).GetComponent<PhotonView>() ?? ((Component)avatar).GetComponentInParent<PhotonView>(); if ((Object)(object)_photonView == (Object)null) { SemiKick.LogError("[SemiKick] Не удалось найти PhotonView на объекте " + ((Object)avatar).name + "!"); return; } _isLocal = !SemiFunc.IsMultiplayer() || _photonView.IsMine; SemiKick.LogInfo($"[SemiKick] KickAnimHandler: PhotonView найден, IsMine={_photonView.IsMine}, IsMultiplayer={SemiFunc.IsMultiplayer()}, isLocal={_isLocal}, ViewID={_photonView.ViewID}"); if (_isLocal) { SemiKickRunner semiKickRunner = Object.FindObjectOfType<SemiKickRunner>(); if ((Object)(object)semiKickRunner != (Object)null) { semiKickRunner.SetLocalPlayer(this); SemiKick.LogInfo("[SemiKick] KickAnimHandler: локальный игрок зарегистрирован в SemiKickRunner, Avatar передан."); } else { SemiKick.LogWarning("[SemiKick] SemiKickRunner не найден на сцене! Локальный Avatar не будет доступен для knockback."); } } SemiKick.LogInfo($"[SemiKick] KickAnimHandler успешно инициализирован (Local: {_isLocal}, ViewID: {_photonView.ViewID})"); } public void PerformKick(Vector3? stretchTargetWorldPos = null) { //IL_006c: 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) Debug.Log((object)string.Format("[JSONAnimation] KickAnimHandler.PerformKick вызван для {0}: _animPlayer={1}, Multiplayer={2}, stretchTarget={3}.", ((Object)(object)_avatar != (Object)null) ? ((Object)_avatar).name : "NULL", ((Object)(object)_animPlayer != (Object)null) ? "не NULL" : "NULL", GameManager.Multiplayer(), stretchTargetWorldPos.HasValue ? ((object)stretchTargetWorldPos.Value/*cast due to .constrained prefix*/).ToString() : "NULL")); if ((Object)(object)_animPlayer != (Object)null) { _animPlayer.PlayKick(stretchTargetWorldPos); } else { Debug.LogWarning((object)"[JSONAnimation] KickAnimHandler.PerformKick: _animPlayer == NULL — анимация физически не может проиграться, т.к. компонент не был передан при Initialize (см. PlayerAvatarVisualsPatch)."); } if ((Object)(object)_photonView != (Object)null && GameManager.Multiplayer()) { _photonView.RPC("RPC_PlayKick", (RpcTarget)1, Array.Empty<object>()); } } [PunRPC] public void RPC_PlayKick() { if ((Object)(object)_animPlayer != (Object)null) { _animPlayer.PlayKick(); } } private void TryForceTumble(Vector3 force) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0061: Unknown result type (might be due to invalid IL or missing references) PlayerTumble tumbleComponent = InternalAccessors.GetTumbleComponent(_avatar); if (!((Object)(object)tumbleComponent == (Object)null)) { Vector3 val = Vector3.Lerp(((Vector3)(ref force)).normalized, Vector3.up, 0.6f); float magnitude = ((Vector3)(ref force)).magnitude; tumbleComponent.TumbleRequest(true, false); tumbleComponent.TumbleForce(val * magnitude); tumbleComponent.TumbleTorque(-((Component)_avatar).transform.right * magnitude); tumbleComponent.TumbleOverrideTime(1.5f); SemiKick.LogInfo($"[SemiKick] ГАРАНТИРОВАННЫЙ ПОЛЕТ для {((Object)_avatar).name}. Сила: {magnitude}"); } } public void RequestGenericKick(Action applyAction) { if (InternalAccessors.CanDoStuff(Avatar)) { ((MonoBehaviour)this).StartCoroutine(DelayedKickCoroutine(applyAction)); } } private IEnumerator DelayedKickCoroutine(Action applyAction) { if ((Object)(object)pc == (Object)null) { SemiKick.LogWarning("[KickAnimHandler.DelayedKickCoroutine] PlayerController не найден на сцене! Если что сейчас мод ляжет НАХУЙ, хорошо?"); } ((Behaviour)pc).enabled = false; yield return (object)new WaitForSeconds(0.5f); float duration = 0.11f; float totalKick = 49.04f; float elapsed = 0f; float lastHeight = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; float num = Mathf.Sin(Mathf.Min(1f, elapsed / duration) * (float)Math.PI * 0.5f); float num2 = totalKick * num; float num3 = num2 - lastHeight; CameraAim.Instance.AdditiveAimY(0f - num3); lastHeight = num2; yield return null; } ((Behaviour)pc).enabled = true; applyAction?.Invoke(); } public void RequestKick(Vector3 force, bool forceTumble = false) { //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) RequestGenericKick(delegate { //IL_0013: 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_002c: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMasterClientOrSingleplayer()) { _avatar.ForceImpulse(force); if (forceTumble) { TryForceTumble(force); } } else if ((Object)(object)_photonView != (Object)null) { _photonView.RPC("RequestKickRPC", (RpcTarget)2, new object[2] { force, forceTumble }); } }); } [PunRPC] private void RequestKickRPC(Vector3 force, bool forceTumble, PhotonMessageInfo _info = default(PhotonMessageInfo)) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _avatar.ForceImpulse(force); if (forceTumble) { TryForceTumble(force); } } } internal static class KnockbackCalculator { public static void Apply(PlayerAvatar kicker, float targetMass, float kickForce, Vector3 kickDirection) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) SemiKick.LogInfo(string.Format("[SemiKick] KnockbackCalculator.Apply вызван: kicker={0}, targetMass={1}, kickForce={2}, direction={3}", ((Object)(object)kicker != (Object)null) ? ((Object)kicker).name : "NULL", targetMass, kickForce, kickDirection)); if ((Object)(object)kicker == (Object)null) { SemiKick.LogWarning("[SemiKick] KnockbackCalculator.Apply: kicker == null (localPlayerHandler.Avatar не был передан?), выхожу без эффекта."); return; } if (targetMass <= 0f) { SemiKick.LogWarning($"[SemiKick] KnockbackCalculator.Apply: targetMass={targetMass} <= 0, выхожу без эффекта (масса не найдена или объект и правда невесомый)."); return; } if (kickForce <= 0f) { SemiKick.LogWarning($"[SemiKick] KnockbackCalculator.Apply: kickForce={kickForce} <= 0, выхожу без эффекта."); return; } float num = targetMass / kickForce; float num2 = 0.9f; float num3 = 4f; SemiKick.LogInfo($"[SemiKick] KnockbackCalculator: resistanceRatio={num} (targetMass={targetMass} / kickForce={kickForce}), SoftThreshold={num2}, HardThreshold={num3}"); if (num <= num2) { SemiKick.LogInfo("[SemiKick] KnockbackCalculator: resistanceRatio <= SoftThreshold -> без отдачи."); return; } Vector3 val = -((Vector3)(ref kickDirection)).normalized; float num4 = targetMass * 3f; if (num > num3) { float num5 = targetMass * 3f; float num6 = Mathf.Max(num5, 20f); SemiKick.LogInfo($"[SemiKick] KnockbackCalculator: resistanceRatio > HardThreshold -> ТАМБЛ + урон. computedForce={num5}, floor={20f}, итог recoilForce={num6}, direction={val}"); PlayerTumble tumbleComponent = InternalAccessors.GetTumbleComponent(kicker); if ((Object)(object)tumbleComponent != (Object)null) { int num7 = CalculateDamage(num, num3); SemiKick.LogInfo($"[SemiKick] KnockbackCalculator: вызываю tumble.TumbleRequest(true, false) и tumble.ImpactHurtSet(window={0.5f}, damage={num7})"); tumbleComponent.TumbleRequest(true, false); tumbleComponent.ImpactHurtSet(0.5f, num7); } else { SemiKick.LogWarning("[SemiKick] KnockbackCalculator: tumble == null, тамбл/урон НЕ применены, будет только импульс."); } SemiKick.LogInfo($"[SemiKick] KnockbackCalculator: вызываю kicker.ForceImpulse({val * num6})"); kicker.ForceImpulse(val * num6); } else { float num8 = num4 * 0.3f; SemiKick.LogInfo($"[SemiKick] KnockbackCalculator: Soft < resistanceRatio <= Hard -> лёгкая отдача без тамбла. force={num8}, direction={val}"); kicker.ForceImpulse(val * num8); } } private static int CalculateDamage(float resistanceRatio, float hardThreshold) { float num = Mathf.InverseLerp(hardThreshold, hardThreshold * 2f, resistanceRatio); int num2 = Mathf.RoundToInt(Mathf.Lerp(15f, 50f, num)); SemiKick.LogInfo($"[SemiKick] KnockbackCalculator.CalculateDamage: resistanceRatio={resistanceRatio}, t={num}, damage={num2}"); return num2; } } [HarmonyPatch(typeof(PlayerAvatar), "Start")] public static class PlayerAvatar_Start_Patch { [HarmonyPostfix] public static void Postfix(PlayerAvatar __instance) { Debug.Log((object)$"[JSONAnimation] PlayerAvatar_Start_Patch.Postfix вызван для {((Object)__instance).name}, photonView={(Object)(object)__instance.photonView != (Object)null}."); if (!((Object)(object)__instance.photonView == (Object)null)) { KickAnimHandler kickAnimHandler = ((Component)__instance).gameObject.GetComponent<KickAnimHandler>() ?? ((Component)__instance).gameObject.AddComponent<KickAnimHandler>(); PlayerAvatarVisuals componentInChildren = ((Component)((Component)__instance).transform.root).GetComponentInChildren<PlayerAvatarVisuals>(true); Debug.Log((object)($"[JSONAnimation] transform.root.GetComponentInChildren<PlayerAvatarVisuals>(true) на {((Object)__instance).name} (root={((Object)((Component)__instance).transform.root).name}): найдено={(Object)(object)componentInChildren != (Object)null}" + (((Object)(object)componentInChildren != (Object)null) ? $", gameObject.activeSelf={((Component)componentInChildren).gameObject.activeSelf}, activeInHierarchy={((Component)componentInChildren).gameObject.activeInHierarchy}" : "") + ".")); KickAnimationPlayer kickAnimationPlayer = null; if ((Object)(object)componentInChildren != (Object)null) { kickAnimationPlayer = ((Component)componentInChildren).gameObject.GetComponent<KickAnimationPlayer>() ?? ((Component)componentInChildren).gameObject.AddComponent<KickAnimationPlayer>(); Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = "SemiKick.Resources.kick_animation.json"; Debug.Log((object)("[JSONAnimation] Вызываю kickPlayer.InitializeFromEmbeddedResource(jsonPath=" + text + ", rigRoot=" + ((Object)((Component)componentInChildren).transform).name + ") на объекте " + ((Object)((Component)componentInChildren).gameObject).name + ".")); kickAnimationPlayer.InitializeFromEmbeddedResource(text, ((Component)componentInChildren).transform); } else { Debug.LogWarning((object)("[JSONAnimation] PlayerAvatarVisuals НЕ найден на " + ((Object)__instance).name + " (или его детях) — kickPlayer останется NULL, анимация для этого аватара работать не будет.")); } Debug.Log((object)("[JSONAnimation] Передаю kickPlayer=" + (((Object)(object)kickAnimationPlayer != (Object)null) ? "не NULL" : "NULL") + " в KickAnimHandler.Initialize для " + ((Object)__instance).name + ".")); kickAnimHandler.Initialize(kickAnimationPlayer, __instance); } } } internal static class InternalAccessors { private static readonly FieldRef<PlayerAvatar, bool> IsTumblingRef = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isTumbling"); private static readonly FieldRef<PlayerAvatar, bool> IsCrouchingRef = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isCrouching"); private static readonly FieldRef<PlayerAvatar, bool> IsGroundedRef = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isGrounded"); public static Rigidbody GetEnemyRigidbody(EnemyRigidbody enemyRb) { if ((Object)(object)enemyRb == (Object)null) { return null; } Rigidbody value = Traverse.Create((object)enemyRb).Field("rb").GetValue<Rigidbody>(); if ((Object)(object)value == (Object)null) { SemiKick.LogWarning("[SemiKick] InternalAccessors.GetEnemyRigidbody: поле 'rb' вернуло null."); } return value; } public static Enemy GetEnemyFromRigidbody(EnemyRigidbody enemyRb) { if ((Object)(object)enemyRb == (Object)null) { return null; } return Traverse.Create((object)enemyRb).Field("enemy").GetValue<Enemy>(); } public static Rigidbody GetPlayerRigidbody(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return null; } return Traverse.Create((object)player).Field("rb").GetValue<Rigidbody>(); } public static bool GetIsTumbling(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } return Traverse.Create((object)player).Field("isTumbling").GetValue<bool>(); } public static PlayerTumble GetTumbleComponent(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { SemiKick.LogWarning("[SemiKick] InternalAccessors.GetTumbleComponent: player == null."); return null; } PlayerTumble value = Traverse.Create((object)player).Field("tumble").GetValue<PlayerTumble>(); if ((Object)(object)value == (Object)null) { SemiKick.LogWarning("[SemiKick] InternalAccessors.GetTumbleComponent: поле 'tumble' вернуло null для " + ((Object)player).name + "."); return value; } SemiKick.LogInfo("[SemiKick] InternalAccessors.GetTumbleComponent: tumble найден для " + ((Object)player).name + "."); return value; } public static PhotonView GetEnemyPhotonView(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return null; } return Traverse.Create((object)enemy).Field("PhotonView").GetValue<PhotonView>(); } public static EnemyStateStunned GetEnemyStateStunned(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return null; } return Traverse.Create((object)enemy).Field("StateStunned").GetValue<EnemyStateStunned>(); } public static bool CanDoStuff(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } bool num = IsTumblingRef.Invoke(player); bool flag = IsCrouchingRef.Invoke(player); bool flag2 = IsGroundedRef.Invoke(player); return !num && !flag && flag2; } } internal static class KickNetworking { public static void ApplyKickToPlayer(PlayerAvatar player, Vector3 force, bool forceTumble = false) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) KickAnimHandler component = ((Component)player).gameObject.GetComponent<KickAnimHandler>(); if ((Object)(object)component != (Object)null) { component.RequestKick(force, forceTumble); return; } SemiKick.LogWarning("[SemiKick] ApplyKickToPlayer: у " + ((Object)player).name + " нет KickAnimHandler, пинок может не сработать у гостей."); player.ForceImpulse(force); } public static void ApplyKickToValuable(PhysGrabObject physGrabObject, Vector3 force, Vector3 hitPoint) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)physGrabObject == (Object)null) && SemiFunc.IsMasterClientOrSingleplayer()) { Rigidbody rb = physGrabObject.rb; if (!((Object)(object)rb == (Object)null)) { rb.AddForceAtPosition(force, hitPoint, (ForceMode)1); } } } } internal enum KickTargetType { None, Player, Enemy, Valuable } internal struct KickTarget { public KickTargetType Type; public Rigidbody Rigidbody; public Component Component; } internal static class KickTargetClassifier { public static KickTarget ClassifyHit(Collider col) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 KickTarget result = new KickTarget { Type = KickTargetType.None }; PlayerAvatar val = ((Component)col).GetComponentInParent<PlayerAvatar>(); if ((Object)(object)val == (Object)null) { val = ((Component)((Component)col).transform.root).GetComponentInChildren<PlayerAvatar>(); } if ((Object)(object)val != (Object)null) { result.Type = KickTargetType.Player; result.Component = (Component)(object)val; result.Rigidbody = InternalAccessors.GetPlayerRigidbody(val); return result; } EnemyRigidbody componentInParent = ((Component)col).GetComponentInParent<EnemyRigidbody>(); if ((Object)(object)componentInParent != (Object)null) { Enemy enemyFromRigidbody = InternalAccessors.GetEnemyFromRigidbody(componentInParent); if ((Object)(object)enemyFromRigidbody != (Object)null) { if ((int)enemyFromRigidbody.CurrentState == 11) { return result; } result.Type = KickTargetType.Enemy; result.Component = (Component)(object)enemyFromRigidbody; result.Rigidbody = InternalAccessors.GetEnemyRigidbody(componentInParent); return result; } } ValuableObject componentInParent2 = ((Component)col).GetComponentInParent<ValuableObject>(); if ((Object)(object)componentInParent2 != (Object)null) { PhysGrabObject component = ((Component)componentInParent2).GetComponent<PhysGrabObject>(); if ((Object)(object)component == (Object)null) { return result; } if (component.grabbed) { return result; } result.Type = KickTargetType.Valuable; result.Component = (Component)(object)component; result.Rigidbody = component.rb; return result; } PhysGrabObject componentInParent3 = ((Component)col).GetComponentInParent<PhysGrabObject>(); if ((Object)(object)componentInParent3 != (Object)null) { if (componentInParent3.grabbed) { return result; } result.Type = KickTargetType.Valuable; result.Component = (Component)(object)componentInParent3; result.Rigidbody = componentInParent3.rb; return result; } return result; } } [BepInPlugin("quxxciy.semikick", "SemiKick", "0.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SemiKick : BaseUnityPlugin { private Harmony harmony; private Keybind kickKeybind; private static bool runnerCreated; internal static ManualLogSource LoggerInstance; public const string UpgradeId = "SemiKick_KickUpgrade"; private void Awake() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown LoggerInstance = ((BaseUnityPlugin)this).Logger; kickKeybind = Keybinds.Bind("Kick", "<Keyboard>/f"); LogInfo("SemiKick загружен, бинд зарегистрирован."); ItemContent val = LoadItemContentFromEmbeddedBundle("SemiKick.Resources.SemiKick.repobundle", "REPOLib_Item Upgrade Kick"); Item val2 = null; if ((Object)(object)val != (Object)null) { Items.RegisterItem(val); ItemAttributes component = ((Component)val.Prefab).GetComponent<ItemAttributes>(); if ((Object)(object)component != (Object)null) { val2 = component.item; } else { LogError("На префабе нет компонента ItemAttributes."); } } Upgrades.RegisterUpgrade("SemiKick_KickUpgrade", val2, (Action<PlayerAvatar, int>)OnUpgradeStart, (Action<PlayerAvatar, int>)OnUpgradeApplied); harmony = new Harmony("quxxciy.semikick"); harmony.PatchAll(); SceneManager.sceneLoaded += OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0028: 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) //IL_0033: Expected O, but got Unknown if (!runnerCreated) { LogInfo("Первая сцена загружена: " + ((Scene)(ref scene)).name + ", создаю Runner."); GameObject val = new GameObject("SemiKickRunner"); Object.DontDestroyOnLoad((Object)val); val.AddComponent<SemiKickRunner>().InitKey(kickKeybind); runnerCreated = true; SceneManager.sceneLoaded -= OnSceneLoaded; } } private ItemContent LoadItemContentFromEmbeddedBundle(string resourceFileName, string itemContentAssetName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith(resourceFileName)); if (text == null) { LogError("Embedded resource '" + resourceFileName + "' не найден."); return null; } Stream? manifestResourceStream = executingAssembly.GetManifestResourceStream(text); MemoryStream memoryStream = new MemoryStream(); manifestResourceStream.CopyTo(memoryStream); manifestResourceStream.Dispose(); AssetBundle val = AssetBundle.LoadFromMemory(memoryStream.ToArray()); memoryStream.Dispose(); if ((Object)(object)val == (Object)null) { LogError("Не удалось загрузить AssetBundle из памяти."); return null; } ItemContent obj = val.LoadAsset<ItemContent>(itemContentAssetName); if ((Object)(object)obj == (Object)null) { LogError("ItemContent '" + itemContentAssetName + "' не найден в бандле."); } return obj; } private ItemContent LoadItemContentFromFile(string bundleFileName, string itemContentAssetName) { string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), bundleFileName); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищу бандл по пути: " + text)); if (!File.Exists(text)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Файл бандла не найден по пути: " + text)); return null; } AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"AssetBundle.LoadFromFile вернул null — файл повреждён или не тот формат."); return null; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("AssetBundle загружен. Ассеты внутри: " + string.Join(", ", val.GetAllAssetNames()))); ItemContent obj = val.LoadAsset<ItemContent>(itemContentAssetName); if ((Object)(object)obj == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("ItemContent с именем '" + itemContentAssetName + "' НЕ найден в бандле.")); return obj; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"ItemContent успешно загружен!"); return obj; } public static void Log(LogLevel level, object data) { } public static void LogInfo(object data) { Log((LogLevel)16, data); } public static void LogDebug(object data) { Log((LogLevel)32, data); } public static void LogWarning(object data) { Log((LogLevel)4, data); } public static void LogError(object data) { Log((LogLevel)2, data); } private static void OnUpgradeStart(PlayerAvatar player, int level) { LogInfo(string.Format("[Start] {0} имеет {1} уровня {2}", ((Object)player).name, "SemiKick_KickUpgrade", level)); ApplyKickLevelToPlayer(player, level); } private static void OnUpgradeApplied(PlayerAvatar player, int level) { LogInfo(string.Format("[Applied] {0} теперь имеет {1} уровня {2}", ((Object)player).name, "SemiKick_KickUpgrade", level)); ApplyKickLevelToPlayer(player, level); } private static void ApplyKickLevelToPlayer(PlayerAvatar player, int level) { if ((Object)(object)player == (Object)null) { LogWarning("[SemiKick] ApplyKickLevelToPlayer: player == null."); } else { (((Component)player).gameObject.GetComponent<KickAnimHandler>() ?? ((Component)player).gameObject.AddComponent<KickAnimHandler>()).SetKickLevel(level); } } } public class SemiKickRunner : MonoBehaviour { private Keybind kickKeybind; private KickAnimHandler localPlayerHandler; private float kickCooldown = 1.4f; private float cooldownTimer; public void InitKey(Keybind keybind) { kickKeybind = keybind; } public void SetLocalPlayer(KickAnimHandler handler) { localPlayerHandler = handler; SemiKick.LogInfo(string.Format("SemiKickRunner.SetLocalPlayer: handler={0}, Avatar={1}", (Object)(object)handler != (Object)null, ((Object)(object)handler != (Object)null && (Object)(object)handler.Avatar != (Object)null) ? ((Object)handler.Avatar).name : "NULL")); } private void Update() { //IL_0025: 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_008e: Unknown result type (might be due to invalid IL or missing references) if (cooldownTimer > 0f) { cooldownTimer -= Time.deltaTime; } if (SemiFunc.InputDown(kickKeybind.inputKey) && !(cooldownTimer > 0f)) { RaycastHit hit; KickTarget target; bool flag = TryFindKickTarget(out hit, out target); Vector3? stretchTargetWorldPos = (flag ? new Vector3?(((RaycastHit)(ref hit)).point) : ((Vector3?)null)); if ((Object)(object)localPlayerHandler != (Object)null) { localPlayerHandler.PerformKick(stretchTargetWorldPos); } else { SemiKick.LogWarning("SemiKickRunner.Update: localPlayerHandler == null, PerformKick пропущен."); } ApplyKickEffects(flag, hit, target); } } private int GetEffectiveKickLevel() { if (!((Object)(object)localPlayerHandler != (Object)null)) { return 0; } return localPlayerHandler.KickLevel; } private bool TryFindKickTarget(out RaycastHit hit, out KickTarget target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) hit = default(RaycastHit); target = default(KickTarget); RaycastHit[] array = Physics.RaycastAll(new Ray(((Component)Camera.main).transform.position, ((Component)Camera.main).transform.forward), 2.3f); if (array.Length == 0) { SemiKick.LogInfo("TryFindKickTarget: рейкаст ни во что не попал."); return false; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); PlayerAvatar val = (((Object)(object)localPlayerHandler != (Object)null) ? localPlayerHandler.Avatar : null); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val2 = array2[num]; SemiKick.LogInfo("TryFindKickTarget: попадание в коллайдер '" + ((Object)((RaycastHit)(ref val2)).collider).name + "' на объекте '" + ((Object)((Component)((RaycastHit)(ref val2)).collider).gameObject).name + "'."); KickTarget kickTarget = KickTargetClassifier.ClassifyHit(((RaycastHit)(ref val2)).collider); SemiKick.LogInfo(string.Format("TryFindKickTarget: классификация -> Type={0}, Component={1}", kickTarget.Type, ((Object)(object)kickTarget.Component != (Object)null) ? ((object)kickTarget.Component).GetType().Name : "NULL")); if (kickTarget.Type == KickTargetType.Player && (Object)(object)val != (Object)null && (object)kickTarget.Component == val) { SemiKick.LogInfo("TryFindKickTarget: попадание в СВОЕГО персонажа — игнорирую и продолжаю искать дальше."); continue; } hit = val2; target = kickTarget; return true; } SemiKick.LogInfo("TryFindKickTarget: после пропуска своего персонажа других целей не найдено."); return false; } private void ApplyKickEffects(bool found, RaycastHit hit, KickTarget target) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Expected O, but got Unknown //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Expected O, but got Unknown //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) if (!found) { SemiKick.LogInfo("ApplyKickEffects: цель не найдена, выхожу без эффектов."); return; } if (!InternalAccessors.CanDoStuff(localPlayerHandler?.Avatar)) { SemiKick.LogInfo("Не устойчивая конструкция - пропуск."); return; } if (target.Type != KickTargetType.Player && target.Type != KickTargetType.Enemy && target.Type != KickTargetType.Valuable) { SemiKick.LogInfo("ApplyKickEffects: цель не валидна (None/неизвестный тип), выхожу без эффектов."); return; } Vector3 direction = ((Component)Camera.main).transform.forward; int effectiveKickLevel = GetEffectiveKickLevel(); float force = SemiKickSettings.GetKickForce(effectiveKickLevel); SemiKick.LogInfo($"ApplyKickEffects: рассчитанная сила force={force} (baseForce={1.4f}, effectiveLevel={effectiveKickLevel}, levelMultiplier={0.7f})"); float num = Mathf.Clamp(force * 0.05f, 4f, 14f); if ((Object)(object)GameDirector.instance != (Object)null && (Object)(object)GameDirector.instance.CameraShake != (Object)null) { SemiKick.LogInfo($"ApplyKickEffects: вызываю CameraShake.Shake(strength={num}, time={0.05f})"); GameDirector.instance.CameraShake.Shake(num, 0.05f); } else { SemiKick.LogWarning("ApplyKickEffects: GameDirector.instance или CameraShake == null, тряска пропущена."); } PlayerAvatar kicker = (((Object)(object)localPlayerHandler != (Object)null) ? localPlayerHandler.Avatar : null); if ((Object)(object)kicker == (Object)null) { SemiKick.LogWarning("ApplyKickEffects: kicker (Avatar локального игрока) == null — knockback работать не будет для этого пинка."); } switch (target.Type) { case KickTargetType.Player: { bool flag = effectiveKickLevel >= 2; SemiKick.LogInfo($"ApplyKickEffects: цель Player -> KickNetworking.ApplyKickToPlayer (без self-knockback), forceTumble={flag} (effectiveLevel={effectiveKickLevel} >= {2})."); KickNetworking.ApplyKickToPlayer((PlayerAvatar)target.Component, direction * force, flag); break; } case KickTargetType.Enemy: { Enemy enemy = (Enemy)target.Component; EnemyKickReceiver enemyReceiver = ((Component)enemy).GetComponent<EnemyKickReceiver>(); if (!((Object)(object)enemyReceiver != (Object)null)) { break; } float enemyMass = enemyReceiver.GetMass(); SemiKick.LogInfo($"ApplyKickEffects: цель Enemy '{((Object)enemy).name}', mass={enemyMass} -> ставлю в очередь."); if ((Object)(object)localPlayerHandler != (Object)null) { localPlayerHandler.RequestGenericKick(delegate { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemyReceiver == (Object)null || (Object)(object)enemy == (Object)null) { SemiKick.LogWarning("ApplyKickEffects: Враг исчез до момента удара!"); } else { enemyReceiver.SendKick(direction * force); if ((Object)(object)kicker != (Object)null) { KnockbackCalculator.Apply(kicker, enemyMass, force, direction); } } }); } else { enemyReceiver.SendKick(direction * force); KnockbackCalculator.Apply(kicker, enemyMass, force, direction); } break; } case KickTargetType.Valuable: { PhysGrabObject physGrabObject = (PhysGrabObject)target.Component; ValuableKickReceiver valuableReceiver = ((Component)physGrabObject).GetComponent<ValuableKickReceiver>(); if (!((Object)(object)valuableReceiver != (Object)null)) { break; } float valuableMass = (((Object)(object)physGrabObject.rb != (Object)null) ? physGrabObject.rb.mass : 0f); Vector3 hitPoint = ((RaycastHit)(ref hit)).point; if ((Object)(object)localPlayerHandler != (Object)null) { localPlayerHandler.RequestGenericKick(delegate { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)valuableReceiver == (Object)null || (Object)(object)physGrabObject == (Object)null) { SemiKick.LogWarning("ApplyKickEffects: Предмет исчез до момента удара!"); } else { valuableReceiver.RequestKick(direction * force, hitPoint); if ((Object)(object)kicker != (Object)null && (Object)(object)physGrabObject.rb != (Object)null) { KnockbackCalculator.Apply(kicker, valuableMass, force, direction); } } }); } else { valuableReceiver.RequestKick(direction * force, hitPoint); KnockbackCalculator.Apply(kicker, valuableMass, force, direction); } break; } } } } internal static class SemiKickSettings { public const bool EnableLogging = false; public const LogLevel MinLogLevel = (LogLevel)16; public const float BaseForce = 1.4f; public const float LevelMultiplier = 0.7f; public const int PlayerTumbleGuaranteeLevel = 2; public const float ShakeForceMultiplier = 0.05f; public const float ShakeMin = 4f; public const float ShakeMax = 14f; public const float ShakeTime = 0.05f; public const float LegStretchNaturalReach = 0.5f; public const float LegStretchMaxMultiplier = 1.8f; public const int LegStretchAxis = 1; public const float LegStretchLerpSpeed = 8f; public const float KnockbackSoftThreshold = 0.9f; public const float KnockbackHardThreshold = 4f; public const float RecoilForceMultiplier = 3f; public const float KnockbackHardMinForce = 20f; public const float ImpactHurtWindow = 0.5f; public const int ImpactHurtDamageBase = 15; public const int ImpactHurtDamageMax = 50; public static float GetKickForce(int kickLevel) { return 1.4f * (1f + (float)kickLevel * 0.7f); } } internal class ValuableKickReceiver : MonoBehaviourPun { private PhysGrabObject _physGrabObject; private void Awake() { _physGrabObject = ((Component)this).GetComponent<PhysGrabObject>(); } public void RequestKick(Vector3 force, Vector3 hitPoint) { //IL_000d: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMasterClientOrSingleplayer()) { KickNetworking.ApplyKickToValuable(_physGrabObject, force, hitPoint); return; } PhotonView photonView = ((MonoBehaviourPun)this).photonView; if (!((Object)(object)photonView == (Object)null)) { photonView.RPC("RequestKickRPC", (RpcTarget)2, new object[2] { force, hitPoint }); } } [PunRPC] private void RequestKickRPC(Vector3 force, Vector3 hitPoint, PhotonMessageInfo _info = default(PhotonMessageInfo)) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) KickNetworking.ApplyKickToValuable(_physGrabObject, force, hitPoint); } } [HarmonyPatch(typeof(PhysGrabObject), "Awake")] internal static class ValuableKickReceiverPatch { [HarmonyPostfix] private static void Postfix(PhysGrabObject __instance) { if ((Object)(object)((Component)__instance).gameObject.GetComponent<ValuableKickReceiver>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<ValuableKickReceiver>(); } } }