泰拉瑞亚mod开发笔记 1

在开发mod之前,请务必保证你有以下辅助性资源,否则开发的过程将异常困难:

方法论

首先肯定是要按照官方文档过一遍,Wiki介绍了很多基本的修改方式,但是没有详尽列举所有可拓展部分。应该把Wiki教程作为方法论,它告诉哦我们应该如何去修改,大致在那个范围修改,但是具体执行修改还是需要去看源码,去看接口和Hook是如何定义的。

接着就是查看官方的ExampleMod,大部分能拓展的模块它都给出了一个实际的样例。具体的mod内容继承自ModXXX对象(ModItem、ModNPC等)开发的,ExampleMod则给出了一个继承的实例来补充了文档中没有提到的细节。

借助AI工具的辅助,我们可以比较轻松的找出原版代码实现某个机制的具体代码,这对于实现我们设计的机制而言非常有用。

讲完了方法论,我们来针对具体的模块来给出经验之谈。

本地化

这将是花费很多时间的板块,即使你的mod只支持中文,因为必须将文本和代码分离以解耦,否则既不便于多处调用同一段文本,也让代码变得很难看。

官方文档

**硬广:**如果想要有方便的图形化界面同步编辑多个语言文件,可以使用LocalizationEditor

对于本地化文件的结构划分,应该遵循一个原则:能复用的文本尽量复用,不要让相同的文本在多处重复出现,使用换元来解决。比如说下面这样一个简单的饰品:

A_Gear: {
    Tooltip:
        '''
        缓慢再生生命
        强化技能 ‘6767’
        [c/746f6f:啊吧啊吧]
        [c/746f6f:这是背景故事]
        '''
    DisplayName: 洁白的头饰
}

其中可以拆分出来的单元很多,比如说“缓慢再生生命”,“强化技能”,6767,以及[]包围的两行都可以也最好拆分成为独立键,如果“洁白的头饰”这一文本会在其他地方被引用到,那么也要将其设置为单独的Key,比如:

EffectRegen: 缓慢再生生命
SkillEnhance: 强化技能
A: {
    SkillName: 6767
    
    GearDesc:
        '''
        [c/746f6f:啊吧啊吧]
        [c/746f6f:这是背景故事]
        '''

	GearName: 洁白的头饰
}

# 假设你的mod名字叫做XMod
A_Gear: {
    Tooltip:
   
        '''
        {$Mods.XMod.EffectRegen} 
        {$Mods.XMod.SkillEnhance} {$Mods.XMod.A.SkillName}
        {$Mods.XMod.A.GearDesc}
        '''
    DisplayName: {$Mods.XMod.A.GearName}
}

如果我们发现,不同的Gear饰品之间的Tooltip格式都是一样的,区别就是A替换成为了B,C,D,那么更极端一点的做法就是:

EffectRegen: 缓慢再生生命
SkillEnhance: 强化技能
A: {
    SkillName: 6767
    
    GearEffect: "{$Mods.XMod.EffectRegen}"
    
    GearDesc:
        '''
        [c/746f6f:啊吧啊吧]
        [c/746f6f:这是背景故事]
        '''

	GearName: 洁白的头饰
}

# 假设你的mod名字叫做XMod
Tooltip:
	'''
	{0}{$Mods.XMod.SkillEnhance} {1}
	{2}
	'''

然后在代码里面格式化LocalizaedText,从而完全不需要每多出一个Item就手动拼接一次,最大程度减少重复。

货币系统

护卫奖章是原版的特殊货币,是独立于原版四币的货币系统,tmodloader自带提供了一个方便的实现CustomCurrencySingleCoin,用于支持单币种货币系统。但是显然,如果想要拓展到多币种系统,或者想要修改货币的显示方式,还是需要自己动手,这就需要继承CustomCurrencySystem。为了到达原版的效果,我们至少要做以下内容:

  • 货币不能作为可交易物品
  • 货币不能显示交易价格
  • 购买时扣钱应该尽量保持货币物体的槽位不变

第一点,通过查看源代码得知,在出售物品之前,ModPlayer.CanSellItem接口将检测这个物体是否能被出售,只需在这一层拦截,实现如下:

public override bool CanSellItem(NPC vendor, Item[] shopInventory, Item item)
{
    if (item.ModItem is Currency) return false;

    return base.CanSellItem(vendor, shopInventory, item);
}

第二点,需要修改货币Item对应的Tooltip显示,在显示之前ModItem.ModifyTooltips接口将给出自定义Tooltip的操作空间,这也是最好的拦截接口,实现如下:

public override void ModifyTooltips(List<TooltipLine> tooltips)
{
    var ptl = tooltips.FirstOrDefault(tl => tl.Name == "Price");
    if (ptl != null) ptl.Hide();
}

第三点,需要修改货币交易时的操作接口,CustomCurrencySystem.TryPurchase接口负责具体的货币交易,这里的实现比较复杂,但是逻辑很简单,就是先尽可能地从已有的而货币中扣款,不涉及到进位。如果这一轮之后还有余款,则破开一个比余款多的货币,然后执行找零。

BossBar生命条