# 写在前面

我们知道在游戏中,有两种卡牌交互方式:拖动交互和点击按钮。

想要检测这两种交互动作,就需要patch对应的函数。

1720931606511.png

1720931623389.png

# 猜函数

# 拖动交互

# 寻找

在ME中,是在cardinteraction中添加拖动交互,因此先在dnSpy中搜索cardinteraction,发现没有特别符合的函数。

1720934301361.png

在ME中,除了属性名称,还有这个属性对应的类型,可以看出来cardinteraction是一个list列表,里面存放的是CardOnCardAction类型数据。

1720934439926.png

搜索CardOnCardAction,发现了一个CardOnCardActionRoutine,翻译过来就是卡对卡行动套路,看着挺像那么回事的。

1720934661321.png

private IEnumerator CardOnCardActionRoutine(CardOnCardAction _Action, InGameCardBase _GivenCard, InGameCardBase _ReceivingCard, bool _FastMode)

经过测试,卡牌拖动交互时,会触发这个函数。

# 测试

测试过程如下:进入游戏后选择上方的Hooks按钮,在弹出来的页面中,输入GameManager,然后点击View Methods,在下方继续输入CardOnCardActionRoutine后,找到对应的函数,点击左侧的Hooks,直到上方显示如图信息。

1720952309157.png

利用Tab控制台,随便调出具有拖动交互的卡牌,例如钓鱼竿,然后拖到海上钓鱼。

可以在log控制台中看到如下信息,说明拖动交互过程中,确实执行了这个函数。

1720952474360.png

# 按钮交互

# 寻找

在ME中,是在DismantleAction中添加按钮交互,直接搜索DismantleAction或者DismantleCardAction是比较难找到对应函数的,但是我们可以根据之前拖动交互的函数曲线救国。

查看CardOnCardActionRoutine的代码,可以发现在函数结束前,调用了另一个函数ActionRoutine,根据翻译,以及查看该函数代码,可以发现执行了大量Action相关的代码。初步推断所有Action都由此函数进行结算。

1720955710245.png

# 测试

使用Unity Explorer的Hooks功能,对ActionRoutine函数进行Hook操作。然后进行任意DismantleAction动作(这里是吃了一个芒果),可以在log控制台中看到调用了ActionRoutine函数。

1720955973225.png

1720956047243.png

# 总结

在猜函数阶段,是需要一部分代码基础的,至少需要能够看懂该函数的大致行为和作用。当然,对于交互或改卡这类常用操作来说,知道之后就可以一直用。

如果实在找不到能用的函数,也可以在群里咨询大佬。

# 写代码

ActionRoutine函数和之前patch过的GameLoad函数有一些区别,可以看到GameLoad函数前面的返回值是void,而ActionRoutine函数前面的返回值是IEnumerator

1720956947204.png

1720957099329.png

# 协程函数

  1. 协程函数只能使用postfix

  2. 把patch函数的返回值从void改成IEnumerator ,然后入参添加IEnumerator result(必须为第一个参数)。

  3. 需要添加一句yield return result;

  4. 由于协程函数只能使用postfix,在yield return result前的代码可以近似认为是prefix,后的代码可以近似认为是postfix

[HarmonyPostfix, HarmonyPatch("ActionRoutine")]
public static IEnumerator ActionRoutine_Postfix(IEnumerator result)//新加的
{
    Debug.LogWarning("ActionRoutine1");
    yield return result;//新加的
    Debug.LogWarning("ActionRoutine2");
}

# 示例

之前写过一个物品耐久合并,将两把50%耐久的长矛拖到一起,可以合成为一根100%耐久的长矛。

具体实现如下:在拖动交互进行前,先记录两把长矛的耐久(prefix),然后yield return result执行原函数,将拖过去的长矛销毁,原函数执行完成后,再修改另一把长矛的耐久(postfix)。

public static IEnumerator CardOnCardActionRoutine_Postfix(IEnumerator result, InGameCardBase _GivenCard,
    InGameCardBase _ReceivingCard)
{
    float usage1 = _GivenCard.CurrentUsageDurability;
    float usage2 = _ReceivingCard.CurrentUsageDurability;
    yield return result;
    _ReceivingCard.CurrentUsageDurability = usage1 + usage2;
}

# 小知识

在写代码时,如果要用到原函数的参数,就把这个参数复制过来就行,不要修改名称。

1720959368146.png

1720959441672.png

編集日

*~( ̄▽ ̄)~[お茶]を一杯ください

Coldwinds WeChat 支払う

WeChat 支払う

Coldwinds Alipay

Alipay