跳至正文

第一个远程武器——手枪 – 1.4再版

  • 原作者:裙子 / 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); 第一个参数是合成组的名字(不是游戏里面的名字),第二个是所需数量

如果想用原版的合成组,可以这样

没错,它还有一个第一个参数是int类型的重载

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.DamageTypeDamageClass.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的自动补全将就一下吧

练习

现在,对这把枪的属性进行一些修改,来验证自己是否真的理解了这篇教程,如果有不懂的欢迎提问哦。

  1. 把这把枪射速改为两秒17发,并且百分百暴击
    首先,计算一下两秒17发大概要多快的速度。
    两秒=\(120\)帧,所以每一发需要\(120/17 = 7.05\)帧,于是我们有
    item.useTime = 7;
    item.useAnimation = 7;
    

    接下来改暴击率,由于有4点基础暴击率,所以我们只需要把crit设为96就行了

  2. 让这把枪射出火箭
    你可以通过修改shoot属性或者useAmmo属性来达成
    // 方法1
    item.shoot = ProjectileID.RocketIV;
    // 方法2,背包里要有火箭
    item.useAmmo = AmmoID.Rocket;
  3. 把这把枪的合成方式改为,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();
    
  4. 把上一章的模板剑改为射出泰拉之刃的弹幕
    // 注意添加合适的射出速度
    item.shoot = ProjectileID.TerraBeam;

进阶

  1. 探索一下Item.shootSpeed,这个属性,观察一下它在速度比较大(超过16),和比较小的情况下会出现什么现象。试一下不同的弹幕,看看有哪些弹幕会被这个射速所影响?
  2. 如果想让魔法武器拥有蓝耗,应该设置什么属性?魔法武器能不能使用弹药?
  3. 如果想让物品在铁砧或者工作台合成,应该怎么做?如果想让物品支持铅块铁块合成,应该怎么做?
  4. 修改一下Item.widthItem.height,看看它对武器的使用有什么影响。
  5. 如果想让Item.useStyle = 5,同时贴图又要斜着,该怎么做?(想想法杖)
  6. 有了Item.useTurn = true;以后最好就不要加弹幕了,要有弹幕的武器最好把Item.useTurn这个属性设为false,为什么呢?

《第一个远程武器——手枪 – 1.4再版》有2个想法

  1. 关于进阶5:在1.4examplemod里没有法杖,可能需要去1.3里找(1.4exmod文件夹下的Old文件夹内有1.3的代码)
    ——来自某个试图自己研究找不到答案的小萌新的吱吱

  2. 给新人的答案(我也就只能在入门教学里发答案了):

    【事先声明,我的答案可能存在误差,还是建议自己去试试】

    1:有行动能力AI的弹幕不会一直受到速度的影响(但是可能会受影响一段时间):
    比如说至尊灾厄的红月,很快又会追踪你,但是会离开一段距离
    大部分悠悠球无视该效果(好像是的,我在1.3tml测试过,不知道现在咋样)
    2:Item.mana = XXX;
    3:第一个写两个合成表,第二个用合成组(也可以写两个)
    4:忘了,自己去试
    5:有人回答了,我就摸了
    (如果是我我就写手持弹幕)
    6:避免出现阴间情况(建议自己试下)

发表回复