编写你自己的法术 - Electroblob77/Wizardry GitHub Wiki
本页面将介绍如何让你自己编写更多法术加入到游戏内。
- 一个添加法术的附属模组。你需要先完成开发附属模组的所有步骤。
- 了解关于 JSON 的基础知识。
- 对法术足够的想象力! 限制你的只有你的想象力和编程能力, 尽管后者可以通过不断地训练提高 - 如果你有困难,可以到MOD社区求助。
首先,你需要编写一个新的类来存放你的法术,这是给你运行代码的地方。新增一个类作为Spell
的拓展。你可以在electroblob.wizardry.spell
包内找到Spell
类。 我为 Javadoc 写了一个完整的注释去说明类中的方法和字段,我推荐你去认真阅读它们。
在这个类中新建一个没有参数的构造函数(constructor),并且调用在Spell
类中的超级构造函数(super constructor)。Spell
中有两个超级构造函数,你需要确保自己添加了一个modID
附加参数。接下来你需要给超级构造函数传递一些参数,这是该函数关于法术的参数信息:
-
modID
你的附属模组的 模组ID。这个是便于巫术学模组区分哪些法术是来自附属模组的。 -
name
未揭秘时你的法术的名称,名称要求是全小写字母,并在单词与单词间加上下划线。 -
action
即EnumAction
, 就是在施法时播放的动画效果。 -
isContinuous
设定为True则玩家需要长按鼠标才能施法,设定为false则只需要按下一次即可。
接下来你需要做的事情就是重写Spell
里面第一个的cast(...)
执行方法。这个控制着你的法术将会如何生效,每当 玩家 释放这个法术的时候 (关于如何让巫师和其它实体释放你的这个咒语的方法,请往下看)。接下来你就要开始编写如何让这些法术起作用的执行方法的代码。你的法术可以是有关任何方面的,所以尽情的发挥你的想象力吧!Forge的强大超乎你的想象,你也可以参照一下原有的法术来尝试着进行编写。
cast(...)
执行方法将返回一个 boolean
来告诉开发人员巫师能否正常释放这个法术。如若正常释放,则返回true,如若不能,则返回false。比如当使用强效治疗这个法术时,如果法术成功治疗了玩家,则返回true,如果施法过程中出现错误或者玩家处于满血状态,则返回false。另外,返回true的时候也意味着 —— 法杖消耗了魔力值或是消耗了对应法术的卷轴。
在
electroblob.wizardry.util
有一个名为WizardryUtilities
的类,你很快就会发现这个类是很有用的 —— 我把这个类设定为我放置模组里各种执行方法的地方,其中的一些执行方法也许也能为你提供灵感。特别是,它包含方块、坐标、实体、动画等的处理方法。
从模组4.2版本起, 所有的法术都有了其对应的JSON文件,而这些文件被我放在了 assets/[modid]/spells
路径中(以前我都是将这些法术写死在编码里的)。因此你也需要为你的法术创建一个JSON文件以便这些法术能被正常的读取。详见 法术属性文件 中关于如何编写此类文件的说明。并且暂时将 base_properties
对象留空 —— 便于你稍后添加关于这个法术的具体属性。
游戏加载过程中,巫术学模组将自动读取每一个法术的属性文件,如果有任何一个文件出现错误或者丢失,模组就会向控制台输出警告。
为了使你的法术能够出现在游戏中,你需要通过类似方块和物品注册ID的方式为它也注册一个。就如方块和物品一样,每一个法术都有一个对应的实例。在Forge 1.10及更高版本中, 这是通过 注册事件 来完成的。为你的法术注册之前, 先创建一个事件句柄(或者选中一个现有的) 和一个新的执行方法,将两者注册到: RegistryEvent.Register<法术名>
(如果你不知道怎么注册的话,你也可以查看Forge给出的 帮助文档。)。在新创建的执行方法中,创建你的 法术 类的一个新实例,并使用 event.getRegistry().register(法术名)
进行注册。执行方法的编写大致如下:
@SubscribeEvent
public static void register(RegistryEvent.Register<Spell> event){
event.getRegistry().register(new YourSpell());
}
旧的
GameRegistry.register(...)
执行方法残留在Forge中,但由于巫术学模组本身所使用的注册法术的方法与之不同,因此旧的注册执行方法将不会起到任何作用 —— 你必须使用上面的方法对你的法术进行注册。
注册对于法术来说是必要的!如果你成功注册了法术并为其编写了内容的话,你现在在创造模式分类栏里面的法术书堆里面大概就能看到你新注册的法术的法术书了,如果你幸运值拉满的话,你现在就能正常释放你新写的法术了。
如你所见,模组里面的每一个法术都有一个对应的法术图标。所以你需要为你的法术绘制一个图标,这个图标应该和你的法术的实际效果有关。我建议你从一个空白透明的图标开始画起,你可以在 assets/wizardry/textures/spells/none.png
路径中找到空白图标。并在图像编辑软件中开始绘制这个图标 (作者用的是 GIMP) 然后将你绘制好的图标保存为png格式并重命名为 [你法术的英文名].png
然后将其放到 resources/[your mod ID]/assets/textures/spells
路径中。
同样你也需要为你的法术进行 本地化设置 才能给你的法术设置一个好的可读的法术名和法术描述。这些都应该被放入你的 语言文件 中,路径为 assets/[你的模组ID]/lang/en_US.lang
。编写的标准语法是 spell.[英文法术名]
设置为法术名 spell.[英文法术名].desc
设置为法术描述。
只要你一旦能让玩家释放你的法术,那么让巫师也能施展你的法术就不是问题了。这一次,你就需要_重新_写一次 Spell
的 cast(...)
执行方法。你会注意到这个方法和让玩家释放的方法也一些细微的差别:
- 要记住
caster
的参数是EntityLiving
而并非EntityPlayer
。这是因为释放这个法术的实体并非玩家。 - 还有一个所属
EntityLivingBase
的参数target
。 这是NPC施放法术所要瞄准的目标。
除了上述,其它都完全向东。我强烈建议你从其它 cast(...)
执行方法直接复制并只更改上述所提的部分。但具体是否要进行大规模更改还是取决于法术本身。
另外,你还需要重写 Spell.canBeCastByNPCs()
以确保其返回值为true,以便让巫师能释放你的法术。
由于许多咒语彼此相似,因此设立一组常用的超类以储存常见的咒语类型。这可以大大减少使一个咒语工作所需的代码量,并确保所有类似类型的咒语以标准方式工作。
巫术学内有以下所示的标准法术类:
-
SpellArrow
: 适用于需要调用EntityMagicArrow
的投掷物类法术。(见 添加实体) -
SpellBuff
: 适用于需要给施法者增添状态效果的法术 -
SpellConjuration
: 适用于需要召唤物品的法术 (通常这些物品会需要IConjuredItem
这个参数) -
SpellConstruct
: 适用于那些想要在施法者的位置召唤EntityMagicConstruct
的法术(见 添加实体) -
SpellConstructRanged
: 适用于那些想要在指定目标位置召唤EntityMagicConstruct
的法术(见 添加实体) -
SpellProjectile
: 适用于那些想让法术射击出更多EntityMagicProjectile
的法术(见 添加实体) -
SpellMinion
: 适用于那些想调用ISummonedCreature
召唤出实体的法术(见 添加实体) -
SpellRay
: 适用于那些想让自己的法术拥有射线的法术。包括瞬时性法术和持续引导型法术。
Some of these classes are parametrised, meaning a type parameter should be supplied when extending them. This is usually the type of entity the spell summons/shoots.上述其中的一些类是参数化的,这意味着在调用他们的时候你应该提供类型参数 —— 通常是法术召唤/射击的实体类型。
上述已经包括了添加法术的所有基础知识,如果你想要更深入的了解一些更复杂的法术,你可以阅读下面的提示:
- 如果你想为你的法术添加自定义的实体,我也为你提供了一些可供使用的基础类。更多信息见 添加实体
- 如果你想为你的法术增添粒子效果的话,你可以直接调用原版的,如果你想调用巫术学中的粒子效果,你需要使用
Wizardry.proxy.spawnParticle(...)
, 并且将WizardryParticleType
你想生成的粒子效果填入到该方法参数中。 - 如果你想让你的法术能和魔杖相“互动的话”,可见
electroblob.wizardry
里的WandHelper
。