各位读者早午晚上好啊_(:з」∠)_,又是我,霍霍城镇NPC的能手中学生。这一篇我们将好好认识一下ITownNPCProfile以及其使用方法。废话不多说,直接开始!
上一篇教程的传送门在这里~
认识接口
在认识这个东西之前,我们先简单了解一下什么是接口(interface):
举个例子,你开一家制造公司,专门生产“裙子语录机”。但是这个语录机必须遵循某种特定规格,所以你给子公司们下发了图纸,让他们必须比着图纸来造。这个“图纸”就是接口。
(如果你还不明白那就看官方文档去毕竟我也不太能解释的清)
我们今天的主角ITownNPCProfile就是一个接口,它提供了如下几个方法:
当你继承这个接口时,你的类里必须包含以上这些方法。我们后面创建的所有TownNPCProfile都需要比着这个“蓝图”来构建。
TownNPCProfile介绍
它是干啥的?
从这里开始我们直接将其简称为Profile,首先我们当然需要明白这东西是干什么的。
简单来说,Profile的功能就是控制你的NPC被分配到的贴图以及小地图头像还有姓名。普通城镇NPC并不需要太复杂的Profile,如果你的NPC不需要换材质甚至可以不需要Profile,但城镇宠物这种拥有随机外观的会很需要用到。
这一篇我们先介绍其最基础的用法。
它有哪些功能?
无论我们创建何种Profile,都需要继承ITownNPCProfile这个接口,接下来我们就一一介绍上文中提到的那些方法。首先,让我们建立一个Profile并继承该接口:
然后我们会需要在这个类里把上面的那四种方法都填写上。
什么?你懒得打字?没关系,VS会告诉你你的类没有实现这个接口中的哪些方法。只需要将光标放在ITownNPCProfile的后面,使用alt+enter的组合键,再点击“实现接口”,VS就能进行自动补全懒癌狂喜。
来,一个一个的看:
RollVariation,用于随机选取NPC的不同外观,在宠物里会用到,这里就不细说。常规的城镇NPC填0就行了。
GetNameForVariant,用于为NPC选取姓名,实际上这个方法更多是为原版使用的,我们几乎用不到。后文会说明怎么填写。
GetTextureNPCShouldUse,选取NPC使用的贴图,比如让该NPC在派对状态下切换到派对外观。后文会说明怎么填写。
GetHeadTextureIndex,选取NPC使用的小地图头像,一般而言一个NPC只需要一个头像。后文会说明怎么填写。
这里只是简单说一下它们大致的功能,下面然我们来看看该如何构建与使用吧。
如何构建TownNPCProfile?
在上面创建好了一个Profile之后,我们来挨个看一看如何填写它提供给我们的四个方法,让我们先把成品端上来:
//设置该NPC的本体与头像贴图以及姓名的信息,可通用 public class TestTownNPCProfile : ITownNPCProfile { //基础材质路径 string _rootPath; //派对材质路径 string _altPath; //替换用小地图头像 int _altHeadIndex; //在新声明一个此类时对其进行参数设置 public TestTownNPCProfile(string rootPath, string altPath, int altHeadIndex = -1) { _rootPath = rootPath; _altPath = altPath; _altHeadIndex = altHeadIndex; } //随机选择NPC可用的外观,一般用不到 public int RollVariation() => 0; //在不同的外观下会采用哪些名字池,一般用不到,直接如下填写 public string GetNameForVariant(NPC npc) => npc.getNewNPCName(); //设置绘制时使用的贴图,可以用来切换派对贴图与日常贴图 public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc) { //当 切换到派对材质 且 并非图鉴展示 时使用派对皮肤 if (npc.altTexture == 1 && !npc.IsABestiaryIconDummy) { return ModContent.Request<Texture2D>(_altPath); } return ModContent.Request<Texture2D>(_rootPath); } //设置头像贴图 public int GetHeadTextureIndex(NPC npc) { //当 切换到派对材质 且 新头像ID不为-1 时 使用替换用头像 if (npc.altTexture == 1 && _altHeadIndex != -1) { return _altHeadIndex; } return ModContent.GetModHeadSlot(_rootPath + "_Head"); } }
欸欸欸?那个 public TestTownNPCProfile
是个啥?前面怎么没说过啊?
这种写法叫构造方法,我们可以通过这种手段从外部实现对类内部的变量赋值,毕竟这个Profile以后还能拿去给别的NPC用嘛,咱们就写的通用性高一些,以后就不必给每个NPC都建一份Profile了。
首先,我们声明三个需要用到的变量,分别是 _rootPath
:基础材质路径、_altPath
:替换用材质路径和_altHeadIndex
:替换用头像。同样的,在我们的构造方法内也提供了三种参数,分别对应这三个变量。
还是分别来看:
//随机选择NPC可用的外观,一般用不到 public int RollVariation() => 0;
这个在这里不作过多解释。
//在不同的外观下会采用哪些名字池,一般用不到,直接如下填写 public string GetNameForVariant(NPC npc) => npc.getNewNPCName();
npc.getNewNPCName()
就相当于调用了一次 SetNPCNameList()
。
当然你也可以给它加一些通用点缀比如npc.getNewNPCName()+"_Test"
,这样一来你的NPC在生成时其姓名后面就都会带一个“_Test”,比如“测试小伙_Test”。
//设置绘制时使用的贴图,可以用来切换派对贴图与日常贴图 public Asset<Texture2D> GetTextureNPCShouldUse(NPC npc) { //当 切换到派对材质 且 并非图鉴展示 时使用派对皮肤 if (npc.altTexture == 1 && !npc.IsABestiaryIconDummy) { return ModContent.Request<Texture2D>(_altPath); } return ModContent.Request<Texture2D>(_rootPath); }
这个是本篇的重点之一,当派对事件发生时,npc.altTexture
就会变成1,平时这个属性的值为0。而 !npc.IsABestiaryIconDummy
是为了让NPC在图鉴展示时始终保持默认外形,不至于开派对时图鉴内也显示派对外观,当然如果你想这么做也不是不行。
//设置头像贴图 public int GetHeadTextureIndex(NPC npc) { //当 切换到派对材质 且 新头像ID不为-1 时 使用替换用头像 if (npc.altTexture == 1 && _altHeadIndex != -1) { return _altHeadIndex; } return ModContent.GetModHeadSlot(_rootPath + "_Head"); }
本篇的另一个重点,一般来说我们只需要最后一行那个返回值就可以了,但这次我们选择让NPC开派对时跟着换头像。
如果你直接返回了-1那么NPC的头像就不会被呈现在地图上。
看到这儿你会发现这个 GetHeadTextureIndex
怎么是 int 类型啊?因为原版的头像就是 int 类型,而 GetModHeadSlot
的用途就是帮我们把对应路径下的头像转变成 int 类型的值。如果在这个路径下没有发现相应的贴图,就会返回-1。
这样把所有的方法都填好了,就完事儿了吗?当然没有,我们还没有在TestTownNPC里应用这个Profile嘞!
如何使用TownNPCProfile?
建好了Profile之后,想要使用它就很简单了。首先回到我们的TestTownNPC中,插入这么一个重写函数:TownNPCProfile。
这个重写函数本身的构成很简单,但是还记得前面我们提到的NPC头像的切换吗?GetModHeadSlot
只能获取已经被加入的头像,也就是 AutoloadHead
为你自动添加的那个默认头像。这里就来演示一下如何添加新的头像:
//通用路径,方便进行更改 static string rootPath = "TeaNPC/Content/NPCs/Towns/Test/TestTownNPC"; //替换用小地图头像 static int AltHeadSlot; //加载数据,这里用于加载替换用小地图头像 public override void Load() { //将该头像加入游戏内 AltHeadSlot = Mod.AddNPCHeadTexture(Type, rootPath + "_Head_Party"); } //设置NPC的贴图相关属性 public override ITownNPCProfile TownNPCProfile() { return new TestTownNPCProfile(rootPath, rootPath + "_Party", AltHeadSlot); }
首先声明一个 int 类型的变量即 AltHeadSlot
。
然后,插入一个重写函数:Load。这个函数会在你的Mod加载时执行,很适合进行一些初始化操作,这里我们用来添加新头像。
添加新头像用到了这么一个方法:Mod.AddNPCHeadTexture
,第一个参数填写为之添加的NPC的ID即可,后面就是指定的路径。这样一来这个头像就被添加成功了,可以被 GetModHeadSlot
获取到了。
注意一下:这个方法仅适合城镇NPC,Boss有自己专属的AddBossHeadTexture
,不要混着用啊。
最后,在TownNPCProfile中,新声明一个 TestTownNPCProfile
,把我们准备好的参数填进去,就大功告成啦!
这样一来,以后我们创建了一个新的城镇NPC之后,只需要重复使用这次建立好的Profile就行了,方便的同时也减少了代码量。除非有特殊需求,我们将不会再需要建立新的Profile。
展示成果
什么?你说你没有派对贴图?自己画一个去(无慈悲)
总结
有了这个新东西,我们就可以对城镇NPC进行更自由的编辑。还是那句话,只要你有足够的想法,在这上面实现更多有趣的功能完全不是问题。我是中学生,一个专门霍霍城镇NPC的屑仍在学习的模组作者,我们下次再见_(:з」∠)_