- 原作者:裙子 / 2020年3月6日 再版:夜谷紫幽
你应该能在Items文件夹下发现TemplateGun.cs,它就是我们今天要讲的主题。
合成表
这把枪,好像并不能在游戏里面被合成出来。。。
因为这是我特意设置的,为了让你们知道如何创建合成表(笑)
我们先回顾一下上一章那把剑的合成表:
// 物品合成表的设置部分 public override void AddRecipes() { // 1.4的合成表具体写法可以查看下列网址来详细看看,这里只是一个简单的示例 // 这个网址是TML的教程,英文 //https://github.com/tModLoader/tModLoader/wiki/Basic-Recipes // 这个网址是汉化exmod,中文 //https://github.com/Cyrillya/Example-Mod-Zh-Project/blob/master/Content/ExampleRecipes.cs // 生成1个这种物品 var recipe = CreateRecipe(); // 这样可以生成50个 // CreateRecipe(50); // 合成材料,需要10个泥土块 // 哦对了,如果你写俩种相同的材料的话 // 它们会分别显示而不是合并成一个 // (我家门前有两颗树,一颗是枣树,另一颗还是枣树) recipe.AddIngredient(ItemID.DirtBlock, 10); // 以及在工作台旁边 recipe.AddTile(TileID.WorkBenches); // 把这个合成表装进tr的系统里 recipe.Register(); }
Recipe就类似一个合成表管理器,这是TML自带的,可以对原版合成表进行操作。具体来说,常用的操作有
AddIngredient
这个函数的作用是向合成表添加原料,比如
// 合成材料,需要10个泥土块 recipe.AddIngredient(ItemID.DirtBlock, 10); // 合成材料,还需要10个铁块 recipe.AddIngredient(ItemID.IronBar, 10); // 合成材料,还需要100个金块 recipe.AddIngredient(ItemID.GoldBar, 100);
这个函数可以写多个,这样对于同一个Recipe,原料会叠加,上面这个代码在游戏中是这样的:
注意我这里的ItemID.XXX
,这些其实就是物品的ID
如果你使用右键->查看定义
你就会发现,其实ItemID.IronBar
,对应的就是一个数字,代表了铁锭的物品ID
知道了铁锭ID是22,那么我可以写 recipe.AddIngredient(22, 10);
也可以写recipe.AddIngredient(ItemID.IronBar, 10);
后者的好处是意义很清晰,因为22这个数字可以代表的意思太多了,很可能你之后看这段代码就想不起来合成材料是什么了,但是如果你看到ItemID.IronBar
你就能立刻知道这个东西是铁锭。 具体的物品ID可以在wiki找到: https://terraria-zh.gamepedia.com/%E7%89%A9%E5%93%81_ID
那么如果我想要添加Mod物品呢?首先我们必须明确一点,就是Mod物品不存在固定的ID。Mod物品的ID可能随着你加载的Mod数量而 变化所以我们只能动态获取。
TML当然考虑到了这一点,于是我们有了ModContent.ItemType()
。这个函数的使用方法看上去可能有点奇怪,如果我们想把上一章的那把剑加入合成表,我们需要这么写:
// SkirtSword是教程那把剑的类名!! recipe.AddIngredient(ModContent.ItemType<SkirtSword>(), 1);
注意:使用ModContent.XXXType<T>()这类函数通常会让T里面的东西被VS画上红线,此时要用小灯泡进行修复。因为T的值通常需要引用其他命名空间的类。
总之,目前的方法我们已经可以添加Mod物品作为合成原料,效果如图
AddTile
与AddIngredient相似,只不过这个函数是添加合成环境的
当然,你也可以添加两个合成环境
// 在工作台和水晶球旁边才能合成
recipe.AddTile(TileID.WorkBenches);
recipe.AddTile(TileID.CrystalBall);
那么我们可以推测出TileID其实就是一个储存物块ID的类,剩下的就和AddIngredient没区别了。物块ID可以在wiki找到: https://terraria-zh.gamepedia.com/%E5%9B%BE%E6%A0%BC_ID
注:如果要在液体(水,岩浆,蜂蜜)中合成,因为液体并不具备实体物块ID,所以我们不能用TileID完成。但是我们可以使用:
// 水边合成
recipe.AddCondition(Recipe.Condition.NearWater);
// 蜂蜜合成
recipe.AddCondition(Recipe.Condition.NearHoney);
// 岩浆合成
recipe.AddCondition(Recipe.Condition.NearLava);
AddRecipeGroup
(来自某天使写的)
AddRecipeGroup函数的作用是,向合成表添加入一个合成组,那么什么是合成组?
合成组是一堆合成物品的集合,通过写一个合成组,可以削减一大堆的 AddIngredient
这样的好处,举个例子是可以说明的,你绝对不想给一部分是用火把合成的物品,去一个一个火把添加合成表吧(
首先我们找到ModSystem类,输入
这个东西的作用就是向mod添加合成组
接着里面New一个RecipeGroup
是不是很长?别急,我们先一个一个分析
第一个参数是一个Func委托,直接打个括号,用=,后输入合成组在游戏的名字即可Language.GetTextValue(“LegacyMisc.37”)是根据游戏的语言改变的一个叫“任意”的名字(当然也可以直接打一个”任意火把”来代替)
第二个参数是一个int[]类型,具体就是让你输入一大堆物品的ID(mod物品也可以)
最后需要用 RecipeGroup.RegisterGroup("MOD:Torch", group)
来加载这个合成表,这个东西第一个参数是名字,第二个参数是上面的合成组
最后给出一个 金和铁 做合成组的代码
public override void AddRecipeGroups() { base.AddRecipeGroups();//这里是偷懒留下来的产物 RecipeGroup recipeGroup = new RecipeGroup(() => "金或铁", //游戏显示合成组的名字 new int[] { ItemID.GoldOre,//金块 ItemID.IronOre//铁块 });//添加ID RecipeGroup.RegisterGroup("GlodAndIron", recipeGroup);//向游戏添加合成组 }
但是我们有了合成组,我们还没有用呢
我们就要用AddRecipeGroup了
recipe.AddRecipeGroup("MOD:Torch",10);
第一个参数是合成组的名字(不是游戏里面的名字),第二个是所需数量
如果想用原版的合成组,可以这样
ReplaceResult
ReplaceResult 函数的作用就是替换合成表要合成的物品,一个Recipe可以填写两个参数,第一个参数为合成的物品,第二个参数为合成数量(默认为1)
这个函数的第一个参数可以是一个ItemID,或者ModItem,而这段代码用的就是前者
这个函数的第二个参数必须是一个int
// 生成1个泥土
recipe.ReplaceResult(ItemID.DirtBlock);
// 这样是50个泥土
recipe.ReplaceResult(ItemID.DirtBlock, 50);
Register
没啥好说的,就是告诉ModRecipe,这个合成表的信息填完了,可以加入进去了。
如果想要给一个物品加多个合成表也很简单,只要新建一个名字不同的Receipe就好了:
// 第一个合成表
Recipe recipe1 = CreateRecipe();
// ...
// 第二个合成表
Recipe recipe2 = CreateRecipe();
// ...
修改远程武器属性
首先,你需要给这个物品一个合成表,这样你才能在游戏里观察它。(废话)
与刚才神秘之剑的代码相比,枪类武器做出了一点点改动。首先就是useStyle
这个属性变成了5。由于这个改动,我们的贴图也不再是剑类贴图的45斜向上了,而是水平的。
同时Item.DamageType
也被设为了DamageClass.Ranged
,代表这是个远程武器,受远程伤害,暴击加成。当然你也可以让Item.DamageType
为DamageClass.Melee
,对效果没有影响,就是……
如果你真的要拿手枪敲人,那么一定要记得把Item.noMelee
设为false
。这个属性的作用是物品的贴图造不造成伤害,如果true
就是贴图不造成伤害,反之就是造成伤害。如果这是你想要的,那么就像这样
如果需要改暴击属性可以看Item.crit
属性,一般来说,武器都有默认的4点暴击率,如果item.crit = 0
,那么就会有默认的4%暴击率。注意,这个crit
是个整数,而不是小数了。
接下来就是一个非常重要的属性了,shoot
,也就是射出的弹幕
// 决定枪射出点什么和射出的速度的量 // 这里我让枪射出子弹,并且以 (7像素 / 帧) 的速度射出去 item.shoot = ProjectileID.Bullet; item.shootSpeed = 7f;
我们又一次看到XXXID,这种格式了,这次是ProjectileID
,也就是弹幕的ID。具体的ID表可以在wiki找到: https://terraria-zh.gamepedia.com/%E5%B0%84%E5%BC%B9_ID 。需要注意的是如果你设置了shoot
,那么必须要设置一个非0的shootSpeed
才会发射弹幕。shootSpeed
的意思就是弹幕会以什么样的速度从枪口射出,具体多快可能需要你自己感受了,反正7不算很快。尝试修改一下它的属性,看看多快比较合适。
如果要指定一个Mod弹幕,可以使用ModContent.ProjectileType<弹幕的类名>()
,这和Mod物品的ID获取方法是相似的。
最后一个属性稍微有点难理解,item.useAmmo = AmmoID.Bullet;
让这把枪使用任何子弹作为弹幕,并且实际射出的弹幕类型由你背包里的子弹决定,也就是说,假设我背包里有高速子弹,那么这枪就消耗高速子弹射出高速子弹,如果是普通子弹,那么就会消耗普通子弹射出普通子弹。
设置了这个属性前面的item.shoot
填什么已经不重要了,后面讲到弹药会解释shoot
到底会变成什么。
那么同样,这又是一个ID,我们叫它弹药类型ID,但是这个ID在wiki上没有,所以就用VS的自动补全将就一下吧
练习
现在,对这把枪的属性进行一些修改,来验证自己是否真的理解了这篇教程,如果有不懂的欢迎提问哦。
- 把这把枪射速改为两秒17发,并且百分百暴击首先,计算一下两秒17发大概要多快的速度。
两秒=\(120\)帧,所以每一发需要\(120/17 = 7.05\)帧,于是我们有item.useTime = 7; item.useAnimation = 7;
接下来改暴击率,由于有4点基础暴击率,所以我们只需要把
crit
设为96就行了 - 让这把枪射出火箭你可以通过修改
shoot
属性或者useAmmo
属性来达成// 方法1 item.shoot = ProjectileID.RocketIV; // 方法2,背包里要有火箭 item.useAmmo = AmmoID.Rocket;
- 把这把枪的合成方式改为,5个金锭,5个铁锭,25个火把,在铁砧和工作台和水旁边合成,一次可以合成99个参考代码
Recipe recipe = CreateRecipe(99); recipe.AddIngredient(ItemID.GoldBar, 5); recipe.AddIngredient(ItemID.IronBar, 5); recipe.AddIngredient(ItemID.Torch, 25); recipe.AddTile(TileID.WorkBenches); recipe.AddTile(TileID.Anvils); recipe.AddCondition(Recipe.Condition.NearWater); recipe.Register();
- 把上一章的模板剑改为射出泰拉之刃的弹幕
// 注意添加合适的射出速度 item.shoot = ProjectileID.TerraBeam;
进阶
- 探索一下
Item.shootSpeed
,这个属性,观察一下它在速度比较大(超过16),和比较小的情况下会出现什么现象。试一下不同的弹幕,看看有哪些弹幕会被这个射速所影响? - 如果想让魔法武器拥有蓝耗,应该设置什么属性?魔法武器能不能使用弹药?
- 如果想让物品在铁砧或者工作台合成,应该怎么做?如果想让物品支持铅块或铁块合成,应该怎么做?
- 修改一下
Item.width
和Item.height
,看看它对武器的使用有什么影响。 - 如果想让
Item.useStyle = 5
,同时贴图又要斜着,该怎么做?(想想法杖) - 有了
Item.useTurn = true;
以后最好就不要加弹幕了,要有弹幕的武器最好把Item.useTurn
这个属性设为false,为什么呢?
关于进阶5:在1.4examplemod里没有法杖,可能需要去1.3里找(1.4exmod文件夹下的Old文件夹内有1.3的代码)
——来自某个试图自己研究找不到答案的小萌新的吱吱
给新人的答案(我也就只能在入门教学里发答案了):
【事先声明,我的答案可能存在误差,还是建议自己去试试】
1:有行动能力AI的弹幕不会一直受到速度的影响(但是可能会受影响一段时间):
比如说至尊灾厄的红月,很快又会追踪你,但是会离开一段距离
大部分悠悠球无视该效果(好像是的,我在1.3tml测试过,不知道现在咋样)
2:Item.mana = XXX;
3:第一个写两个合成表,第二个用合成组(也可以写两个)
4:忘了,自己去试
5:有人回答了,我就摸了
(如果是我我就写手持弹幕)
6:避免出现阴间情况(建议自己试下)