Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions HsMod/Patcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ public static void PatchAll()
LoadPatch(typeof(Patcher.PatchIGMMessage));
LoadPatch(typeof(Patcher.PatchMercenaries));
LoadPatch(typeof(Patcher.PatchHearthstone));
LoadPatch(typeof(Patcher.PatchAssemble));
LoadPatch(typeof(Patcher.PatchLogArchive));
LoadPatch(typeof(Patcher.PatchBattlegrounds));
LoadPatch(typeof(Patcher.PatchBgsUnlockCollection));
Expand Down
81 changes: 81 additions & 0 deletions HsMod/Patches/PatchAssemble.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using UnityEngine;

namespace HsMod
{
public partial class Patcher
{
public class PatchAssemble
{
private static readonly FieldInfo rarityGemMesh = AccessTools.Field(typeof(Actor), nameof(Actor.m_rarityGemMesh));
private static readonly FieldInfo rarityFrameMesh = AccessTools.Field(typeof(Actor), nameof(Actor.m_rarityFrameMesh));
private static readonly MethodInfo setRendererEnabled = AccessTools.PropertySetter(typeof(Renderer), nameof(Renderer.enabled));
private static readonly MethodInfo setRarityMeshEnabled = AccessTools.Method(typeof(PatchAssemble), nameof(SetRarityMeshEnabled));

[HarmonyPrepare]
public static bool Prepare()
{
// 旧版游戏没有拼装界面;没有可用目标时不能交给 Harmony 处理空列表。
return TargetMethods().Any();
}

[HarmonyTargetMethods]
public static IEnumerable<MethodBase> TargetMethods()
{
Type assembleUIManager = typeof(Actor).Assembly.GetType("AssembleUIManager");
if (assembleUIManager == null)
yield break;

foreach (string methodName in new[] { "OnShowChoices", "ToggleAssembleUIDisplay" })
{
MethodInfo method = AccessTools.DeclaredMethod(assembleUIManager, methodName);
if (method != null)
yield return method;
}
}

[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> result = new List<CodeInstruction>(instructions);
for (int i = 0; i + 3 < result.Count; i++)
{
if (result[i].opcode != OpCodes.Ldfld ||
(!Equals(result[i].operand, rarityGemMesh) && !Equals(result[i].operand, rarityFrameMesh)))
continue;

MethodInfo getComponent = result[i + 1].operand as MethodInfo;
if (result[i + 1].opcode != OpCodes.Callvirt || getComponent == null ||
getComponent.DeclaringType != typeof(GameObject) || getComponent.Name != nameof(GameObject.GetComponent) ||
!getComponent.IsGenericMethod || getComponent.GetGenericArguments()[0] != typeof(Renderer) ||
result[i + 2].opcode != OpCodes.Ldc_I4_0 ||
result[i + 3].opcode != OpCodes.Callvirt || !Equals(result[i + 3].operand, setRendererEnabled))
continue;

// 原地替换以保留跳转标签与异常块,仅保护拼装界面的稀有度装饰。
result[i + 1].opcode = OpCodes.Nop;
result[i + 1].operand = null;
result[i + 3].opcode = OpCodes.Call;
result[i + 3].operand = setRarityMeshEnabled;
}
return result;
}

private static void SetRarityMeshEnabled(GameObject mesh, bool enabled)
{
// 异画卡的宝石与边框可以独立缺省,不能由宝石存在推断边框存在(#334)。
if (mesh == null)
return;

Renderer renderer = mesh.GetComponent<Renderer>();
if (renderer != null)
renderer.enabled = enabled;
}
}
}
}
Loading