你应该能在Items文件夹下发现TemplateGun.cs,它就是我们今天要讲的主题。
合成表
这把枪,好像并不能在游戏里面被合成出来。。。
因为这是我特意设置的,为了让你们知道如何创建合成表(笑)
我们先回顾一下上一章那把剑的合成表:
// 物品合成表的设置部分 public override void AddRecipes() { ModRecipe recipe = new ModRecipe(mod); // 合成材料,需要10个泥土块 recipe.AddIngredient(ItemID.DirtBlock, 10); // 以及在工作台旁边 recipe.AddTile(TileID.WorkBenches); // 生成1个这种物品 recipe.SetResult(this); // 这样可以生成50个 // recipe.SetResult(this, 50); // 把这个合成表装进tr的系统里 recipe.AddRecipe(); }
ModRecipe就类似一个合成表管理器,这是TML自带的,可以对原版合成表进行操作。具体来说,常用的操作有
AddIngredient
这个函数的作用是向合成表添加原料,比如
// 合成材料,需要10个泥土块 recipe.AddIngredient(ItemID.DirtBlock, 10); // 合成材料,还需要10个铁块 recipe.AddIngredient(ItemID.IronBar, 10); // 合成材料,还需要100个金块 recipe.AddIngredient(ItemID.GoldBar, 100);
这个函数可以写多个,这样对于同一个ModRecipe,原料会叠加,上面这个代码在游戏中是这样的:
注意我这里的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的值通常需要引用其他命名空间的类。
这么写是最推荐的写法,原因有点复杂,目前阶段不太好解释。如果你不喜欢这种写法,还可以这么写:
recipe.AddIngredient(mod, "SkirtSword", 1);
这两种都可以,但是后者只能获取当前Mod的物品,如果要获取其他Mod的物品后面会讲到。你最多可以加14个合成材料,这是泰拉瑞亚本体规定的。
总之,目前的方法我们已经可以添加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.needWater = true; // 蜂蜜合成 recipe.needHoney = true; // 岩浆合成 recipe.needLava = true;
AddRecipeGroup
(来自某天使写的)
AddRecipeGroup函数的作用是,向合成表添加入一个合成组,那么什么是合成组?
合成组是一堆合成物品的集合,通过写一个合成组,可以削减一大堆的 AddIngredient
这样的好处,举个例子是可以说明的,你绝对不想给一部分是用火把合成的物品,去一个一个火把添加合成表吧(
首先我们找到mod主类,输入
这个东西的作用就是向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);
第一个参数是合成组的名字(不是游戏里面的名字),第二个是所需数量
如果想用原版的合成组,可以这样
SetResult
SetResult函数的作用就是确定合成表要合成的物品,当然,一个ModRecipe只能有一个合成出来的物品。
这个函数的第一个参数可以是一个ItemID,或者ModItem,而这段代码用的就是后者
// 生成1个这种物品 recipe.SetResult(this); // 这样可以生成50个 // recipe.SetResult(this, 50);
这个this
在这里指代的就是当前我们正在写的这个物品,当然你可以不合成这个物品,而是合成原版物品,这时候就需要:
// 合成原版铁剑 recipe.SetResult(ItemID.IronBroadsword);
使用ItemID了,ItemID真是一个非常常用的类呢,大家一定要学会如何使用它。
AddRecipe
没啥好说的,就是告诉ModRecipe,这个合成表的信息填完了,可以加入进去了。
如果想要给一个物品加多个合成表也很简单,只要新建一个名字不同的ModReceipe就好了:
// 第一个合成表 ModRecipe recipe1 = new ModRecipe(mod); // ... recipe1.AddRecipe(); // 第二个合成表 ModRecipe recipe2 = new ModRecipe(mod); // ... recipe2.AddRecipe();
修改远程武器属性
首先,你需要给这个物品一个合成表,这样你才能在游戏里观察它。(废话)
与刚才神秘之剑的代码相比,枪类武器做出了一点点改动。首先就是useStyle
这个属性变成了5。由于这个改动,我们的贴图也不再是剑类贴图的45斜向上了,而是水平的。
同时item.ranged
也被设为了true
,代表这是个远程武器,受远程伤害,暴击加成。当然你也可以让item.melee
为true
,对效果没有影响,就是……
如果你真的要拿手枪敲人,那么一定要记得把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个参考代码
ModRecipe recipe = new ModRecipe(mod); recipe.AddIngredient(ItemID.GoldBar, 5); recipe.AddIngredient(ItemID.IronBar, 5); recipe.AddIngredient(ItemID.Torch, 25); recipe.AddTile(TileID.WorkBenches); recipe.AddTile(TileID.Anvils); recipe.needWater = true; recipe.SetResult(this, 99); recipe.AddRecipe();
- 把上一章的模板剑改为射出泰拉之刃的弹幕
// 注意添加合适的射出速度 item.shoot = ProjectileID.TerraBeam;
进阶
- 探索一下
item.shootSpeed
,这个属性,观察一下它在速度比较大(超过16),和比较小的情况下会出现什么现象。试一下不同的弹幕,看看有哪些弹幕会被这个射速所影响? - 如果想让魔法武器拥有蓝耗,应该设置什么属性?魔法武器能不能使用弹药?
- 如果想让物品在铁砧或者工作台合成,应该怎么做?如果想让物品支持铅块或铁块合成,应该怎么做?
- 修改一下
item.width
和item.height
,看看它对武器的使用有什么影响。 - 如果想让
item.useStyle = 5
,同时贴图又要斜着,该怎么做?(想想法杖) - 有了
item.useTurn = true;
以后最好就不要加弹幕了,要有弹幕的武器最好把item.useTurn
这个属性设为false,为什么呢?
熬夜等更新,欸,怎么早上了
不错!
进阶第5个需要加一个item.staff = true;(确信)
orz
进阶五画一个斜着的贴图就好(不)
修改手枪合成的代码那里似乎漏了个?
淦,br
为什么设置手枪合成的那一段br之前的“<”无效啊
修好了
太有用了,以前不会的懂了很多!
怎么设置射弹生成的位置?我这子弹它不从枪口出啊
在Shoot里面用NewProjectile手动发射或者参考这里调整手持位置
我更改过很多次width和height,但是什么变化都没有,这两个属性到底有什么用啊
Item的width和height应该和物品本身(比如丢到地上)的碰撞体积有关,最新版好像这俩属性对物品好像没有任何作用了。
确实,我刚才测出来了
我也是,?+1