本篇教程由作者设定未经允许禁止转载。

前言

幻形者诅咒这个Mod现在仍然处于大量变更阶段,教程可能会没来得及更新,新人创作,有问题请指正。教程目前版本 -> [1.0.76-测试版](Bug太多了,先整个测试版看看还有没有Bug,如果没有就发正式版)

Wiki上只有Mod额外部分的介绍,由于Mod内嵌了起源Origin Furs并使用了部分功能用于形态系统,在Wiki中并没有完整创建一个形态的教程,故创建此教程。


教程中的彩色加粗字的含义:[删除新增](比较上个发布版 如果需要更远古的版本更改历史 请翻阅历史改动对比)开发版修改(Github仓库中最新测试版本(从Actions里下载),一般会在下个版本实装)。如果一整段都为新增或修改,仅在标题处修改颜色。


由于本教程作者不太会制作模型,制作模型的部分就省略。

如果你会编写起源Origin Furs的数据包和资源包,可以直接看fur(新添加了几个功能)、ssc_form、origins_power_extra、lang、rich_lang和额外介绍项这几个新特性来添加新形态。



如果对教程部分有不明白的可以发评论问我,由于数据包添加形态功能(不包括模型部分,那是Origin Furs系统实现的)、变形能力系统和Mask系统的框架是由我编写的(Github用户名xu233333),这方面的问题我看见就会回答的,其他的部分问题我会尽量回答(前提是我会)



文件结构

教程和官方Wiki可能会更新不及时,最新的样例可以看Github仓库,每次修改功能均会更新仓库样例。

资源包

资源包负责实现,本地化文本(lang)、本地化富文本(rich_lang)、玩家动作(player_animation)和Origin Furs的模型文件(模型定义furs 模型geo 材质textures)。

resource_pack ---- 资源包根目录
├─ pack.mcmeta ---- 资源包描述文件
└─ assets
      ├─ example_namespace ---- 自定义命名空间
      │   ├─ lang
      │   │    └─ zh_cn.json ---- 中文本地化文本
      │   ├─ rich_lang
      │   │    └─ zh_cn.json ---- 中文本地化富文本 由Rich Translatable Text实现
      │   └─ player_animation
      │         └─ xxxx.json  ---- 额外形态动画
      │
      └─ orif-defaults ---- Origin Furs 模型命名空间 在里面的模型可以由其他命名空间覆盖
            ├─ furs
            │    └─ <起源数据命名空间>.<起源数据路经>.json ---- 模型定义文件 比如一个形态的起源ID为 "example_namespace:form_example" 那么文件名就是 "example_namespace.form_example.json"
            ├─ geo
            │    └─ xxxx.geo.json ---- 模型文件 文件名由模型定义文件(furs)定义
            └─ textures
                  └─ xxxx.png ---- 模型材质文件 文件名由模型定义文件(furs)定义

数据包

数据包负责实现,形态起源(origins)、能力(powers)、新形态(ssc_form)、挂载能力到已有形态起源(origins_power_extra)和注册起源(origin_layers)。

data_pack ---- 数据包根目录
├─ pack.mcmeta ---- 数据包描述文件
└─ data
      ├─ example_namespace ---- 自定义命名空间
      │   ├─ origins
      │   │    └─ xxxx.json ---- 起源数据 文件名由形态定义文件(ssc_form)定义
      │   ├─ powers
      │   │    └─ xxxx.json ---- 起源能力数据 由起源数据(origins)和能力挂载(origins_power_extra)引用 
      │   ├─ ssc_form
      │   │    └─ xxxx.json ---- 形态定义文件 文件名即为ID的Path 比如 example.json 形态ID就是example_namespace:example
      │   └─ origins_power_extra
      │         └─ xxxx.json ---- 能力挂载项 用于对已有的起源添加额外能力用 一般用于为基础形态添加变形方式
      │
      └─ origins/origin_layers
                 └─ origin.json ---- 用于注册起源数据




文件介绍

示例文件在 Github仓库 在国内可能会无法访问。

lang

路径 - resource_pack/assets/example_namespace/lang/zh_cn.json

示例文件: (为example_namespace:example形态添加详细信息文本)

{
  "codex.form.example_namespace.example.title": "样例标题信息",
  "codex.form.example_namespace.example.appearance": "样例外观信息",
  "codex.form.example_namespace.example.pros": "样例能力信息",
  "codex.form.example_namespace.example.cons": "样例劣势信息",
  "codex.form.example_namespace.example.instincts": "样例本能信息"
}

codex.form.[形态命名空间].[形态路经].[title/appearance/pros/cons/instincts]为形态在幻形者之书中的详细信息,title->标题 appearance->外观 pros->能力 cons->劣势 instincts->本能。



rich_lang

路径 - resource_pack/assets/example_namespace/rich_lang/zh_cn.json

示例文件:(为example_namespace:example形态添加详细信息富文本)

{
  "codex.form.example_namespace.example.title": [{"text":"样例标题信息", "color":"#c67681"}],
  "codex.form.example_namespace.example.appearance": [{"text":"样例外观信息", "color":"#c67681"}],
  "codex.form.example_namespace.example.pros": [{"text":"样例能力信息", "color":"#c67681"}],
  "codex.form.example_namespace.example.cons": [{"text":"样例劣势信息", "color":"#c67681"}],
  "codex.form.example_namespace.example.instincts": [{"text":"样例本能信息", "color":"#c67681"}]
}


同lang,示例让介绍文本的颜色修改为亮红色,格式同原版文本组件。



player_animation

路径 - resource_pack/assets/example_namespace/player_animation/xxxx.json

由BlockBench导出,由形态定义文件调用。



furs

路径 - resource_pack/assets/orif-defaults/furs/example_namespace.form_example.json

示例文件: (定义example_namespace:form_example的模型 从猫形态CV)

{
  "model": "orif-defaults:geo/form_example.geo.json",
  "texture": "orif-defaults:textures/form_example.png",
  "hidden": [
    "leftLeg",
    "rightLeg",
    "rightPants",
    "leftPants",
    "leftSleeve",
    "rightSleeve",
    "leftArm",
    "rightArm",
    "body",
    "jacket",
    "head",
    "hat"
  ],
  "tail_chain": {
    "tail": [0, 1, 2, 3]
  },
  "tail_chain_head": {
    "ear_a": [0],
    "ear_b": [0]
  }
}

model 为BlockBench导出模型[.geo.json]文件。

texture 为模型材质文件。

(可选) texture_mask 1.0.71版本添加的自定义颜色需要的遮罩材质,具体看额外介绍项中的Mask系统。

(可选) overlay 为覆盖皮肤材质文件,用于覆盖皮肤,Mod在狐之使魔形态和悦灵形态使用。

(可选) overlay_mask 同texture_mask只不过覆盖的是overlay。

(可选) hidden 隐藏玩家模型部件,示例文件为全部隐藏。

(可选) tail_chain 父级为躯干的可动部件,一般为尾巴,示例中绑定的尾巴骨骼为tail_0、tail_1、tail_2和tail_3。

(可选) tail_chain_head 父级为头部的可动部件,一般为耳朵,示例中绑定的耳朵骨骼为 ear_a_0和ear_b_0。

(可选) wing_chain_l wing_chain_r 用于翅膀的可动部件。

(可选) IsMultiplyMask 设置自定义颜色遮罩模式为仅正片叠底,具体看额外介绍项中的Mask系统。



geo

路径 - resource_pack/assets/orif-defaults/geo/form_example.geo.json

由BlockBench导出,文件名由furs里model定义。



textures

路径 - resource_pack/assets/orif-defaults/textures/form_example.png

由BlockBench/PS导出,文件名由furs里texture(texture_mask overlay overlay_mask)定义。



origins

路径 - data_pack/data/example_namespace/origins/form_example.json

起源里起源定义。

示例文件:(定义example_namespace:form_example起源的能力 从猫形态CV)

{
  "powers": [
    "shape-shifter-curse:no_render_arm",
    "shape-shifter-curse:form_feral_cat_sp_scale",
    "shape-shifter-curse:form_disable_leg_armor",
    "shape-shifter-curse:form_disable_feet_armor",
    "origins:velvet_paws",
    "origins:scare_creepers",
    "origins:fall_immunity",
    "shape-shifter-curse:form_ocelot_sound",
    "shape-shifter-curse:form_ocelot_sound_hurt"
  ],
  "icon": {
    "item": "minecraft:player_head"
  },
  "order": 0,
  "unchoosable": true,
  "impact": 0
}

powers 为形态能力定义,形态的能力推荐在这里添加。

其他的项在Mod内没有太大作用,从样例CV即可。



powers

路径 - data_pack/data/example_namespace/powers/xxxx.json

起源里能力定义。

示例文件:(to_example_form.json) 由origins和origins_power_extra使用。

{
  "type": "origins:action_on_item_use",
  "entity_action": {
    "type": "shape-shifter-curse:transform_to_form",
    "form_id": "example_namespace:example",
    "instant": true
  },
  "item_condition": {
    "type": "origins:ingredient",
    "ingredient": {
      "tag": "origins:fish"
    }
  }
}

示例文件的效果是,当玩家使用tag为origins:fish的物品(一般为食用),让玩家瞬间变形为example_namespace:example形态。

其他功能可以参考Mod里面的能力定义(Mod的Jar文件根/data/shape-shifter-curse/powers/*.json)。



ssc_form

路径 - data_pack/data/example_namespace/ssc_form/example.json

Mod新增,用来定义新形态。

示例文件: (定义一个ID为example_namespace:example的形态(最小化实现) 效果同猫形态)

{
  "groupIndex": 5
  "phase": "PHASE_SP"
  "bodyType": "FERAL"
  "isCustomForm": true,
  "anim": [
    {
      "state": "ANIM_IDLE",
      "animID": "example_namespace:form_example_idle"
    },
    {
      "state": "ANIM_SNEAK_IDLE",
      "animID": "shape-shifter-curse:form_feral_common_sneak_idle"
    },
    {
      "state": "ANIM_BOAT_IDLE",
      "animID": "shape-shifter-curse:form_feral_common_sneak_idle"
    },
    {
      "state": "ANIM_RIDE_IDLE",
      "animID": "shape-shifter-curse:form_feral_common_sneak_idle"
    },
    {
      "state": "ANIM_WALK",
      "animID": "shape-shifter-curse:form_feral_common_walk",
      "speed": 1.2,
      "fade": 2
    },
    {
      "state": "ANIM_SNEAK_WALK",
      "animID": "shape-shifter-curse:form_feral_common_sneak_walk"
    },
    {
      "state": "ANIM_RUN",
      "animID": "shape-shifter-curse:form_feral_common_run",
      "speed": 2.3
    },
    {
      "state": "ANIM_SWIM_IDLE",
      "animID": "shape-shifter-curse:form_feral_common_float"
    },
    {
      "state": "ANIM_SWIM",
      "animID": "shape-shifter-curse:form_feral_common_swim"
    },
    {
      "state": "ANIM_TOOL_SWING",
      "animID": "shape-shifter-curse:form_feral_common_dig"
    },
    {
      "state": "ANIM_SNEAK_TOOL_SWING",
      "animID": "shape-shifter-curse:form_feral_common_dig"
    },
    {
      "state": "ANIM_JUMP",
      "animID": "shape-shifter-curse:form_feral_common_jump"
    },
    {
      "state": "ANIM_SNEAK_JUMP",
      "animID": "shape-shifter-curse:form_feral_common_jump"
    },
    {
      "state": "ANIM_CLIMB_IDLE",
      "animID": "shape-shifter-curse:form_feral_common_climb"
    },
    {
      "state": "ANIM_CLIMB",
      "animID": "shape-shifter-curse:form_feral_common_climb"
    },
    {
      "state": "ANIM_FALL",
      "animID": "shape-shifter-curse:form_feral_common_fall"
    },
    {
      "state": "ANIM_SLEEP",
      "animID": "shape-shifter-curse:form_feral_common_sleep"
    },
    {
      "state": "ANIM_ATTACK_ONCE",
      "animID": "shape-shifter-curse:form_feral_common_attack"
    },
    {
      "state": "ANIM_SNEAK_ATTACK_ONCE",
      "animID": "shape-shifter-curse:form_feral_common_attack"
    },
    {
      "state": "ANIM_ELYTRA_FLY",
      "animID": "shape-shifter-curse:form_feral_common_elytra_fly"
    },
    {
      "state": "ANIM_CREATIVE_FLY",
      "animID": "shape-shifter-curse:form_feral_common_elytra_fly"
    }
  ]
  "animDefault": {
    "animID": "example_namespace:form_example_idle"
  }
}

如果默认值为可变时 <>内为示例里默认值。

groupID 组ID,用于实现变形逻辑,比如蝙蝠0, 1, 2, 3阶段都在shape-shifter-curse:bat_form组内,默认值为形态ID <example_namespace:example>。

groupIndex 组索引,用于实现变形逻辑,可用值[-2, -1, 0, 1, 2, 3, 5],0-3为阶段形态索引(比如bat_0 bat_1 bat_2 bat_3),5为特殊形态(比如feral_cat_sp),默认值为 0。

phase 阶段,用于实现本能逻辑,目前强绑定groupIndex后续会解绑 只不过目前还有其他功能需要添加 解绑优先度不高。可用值[PHASE_CLEAR,PHASE_0,PHASE_1,PHASE_2,PHASE_3,PHASE_SP] 与groupIndex对应表 -2,-1 -> PHASE_CLEAR   0 -> PHASE_0   1 -> PHASE_1   2 -> PHASE_2   3 -> PHASE_3   5 -> PHASE_SP,默认值为 PHASE_CLEAR。

bodyType 可用值[NORMAL,FERAL],四足形态使用FERAL,其他使用NORMAL,默认值为 NORMAL。

isCustomForm 是否为Custom形态,只在命令中使用此值,如果为true,就需要使用 shape_shifter_curse set_custom_form 而非 shape_shifter_curse set_form来变形,默认为 false。

originID 起源形态ID 用于实现形态能力 默认值为形态ID的NameSpace:form_形态ID的Path <example_namespace:form_example>。
originLayerID 起源LayerID,不推荐修改,默认为 origins:origin。

hasSlowFall 是否拥有动作阶段 ANIM_SLOW_FALL,默认为 false。
overrideHandAnim 从可以由代码添加形态的版本(1.0.7)到当前版本(1.0.72)均没有实际功能,默认为 false。

canSneakRush 是否拥有动作阶段 ANIM_SNEAK_RUSH,默认为 false。

canRushJump  是否拥有动作阶段 ANIM_RUSH_JUMP,默认为 false。

anim 动画,默认为空。

anim/[0]/state 动画阶段,在 Wiki 中Anim项中介绍。

anim/[0]/animID 动画ID,在player_animation - resource_pack/assets/example_namespace/player_animation/xxxx.json文件定义,具体ID在文件中animations项内定义。下面的示例就定义一个 文件所在命名空间:form_example_idle 的动画。

{
    "format_version": "1.8.0",
    "animations": {
       "form_example_idle": { xxxx }
    }
}

anim/[0]/speed 动画速度,默认为1.0。

anim/[0]/fade 动画消退时间,默认为2。

animDefault 同Anim列表中的单项,只是没有state,其他相同,是当anim里没有对应的动画阶段的默认动画。



origins_power_extra

路径 - data_pack/data/example_namespace/origins_power_extra/append_transform.json

用于为起源额外挂载能力(只能添加 不能减少),由于起源不支持合并能力只能覆盖,所以使用这种方法添加变形能力。只推荐为Mod本体的形态添加变形能力,其他形态能力修改在origins里修改。

示例文件: (为form_original_shifter添加变形为样例形态的能力)

{
 "TargetOriginsID": "shape-shifter-curse:form_original_shifter",
 "ExtraPowers": [
   "example_namespace:to_example_form"
 ]
}

TargetOriginsID 挂载目标起源ID。

ExtraPowers 额外的能力列表。



origin_layers/origin.json

路径 - data_pack/data/origins/origin_layer/origin.json

示例文件: (注册example_namespace:form_example起源)

{
  "replace": false,
  "order": 0,
  "enabled": true,
  "origins": [
    "example_namespace:form_example"
  ],
  "allow_random": true,
  "exclude_random": [
  ],
  "allow_random_unchoosable": false,
  "hidden": false
}

replace 必须为false否则会覆盖其他的起源。

origins 填写新的起源ID,不是形态ID。




添加形态步骤

example_namespace为样例命名空间,需要修改为自己的命名空间。

材质包部分

由于本教程作者不太会制作模型 制作模型的部分就省略。

  1. 创建一个材质包文件夹,编写pack.mcmeta 介绍在资源包 - 中文 Minecraft Wiki

  2. 准备形态模型,样例可以看 Github仓库 里面为Mod形态的模型。

  3. 使用BlockBench导出模型和贴图,需要安装AzureLib Animator插件。

    - 模型导出: UI左上角 文件-导出-Export Azurelib.geo Model 导出 (如果没有可以在 文件-转换项目-格式 中修改为AzureLib Animated Model 如果也没有检查一下是否安装AzureLib Animator插件)。

    - 贴图导出: UI左下 纹理 图片上右键 另存为 导出。

    - 动画导出: UI右上角动画模式中修改,修改后在对应文件会出现保存按钮。。

  4. 将模型(.geo.json)放置在resource_pack/assets/orif-defaults/geo/ 文件夹里,贴图(.png)放置在resource_pack/assets/orif-defaults/textures/文件夹里,为了美观可以将材质创建文件夹,动画放在resource_pack/assets/example_namespace/player_animation/文件夹里。

  5. 编写furs文件。

    1. 将模型(.geo.json)的路径填到model,贴图(.png)的路径填到texture。

    2. 根据模型决定隐藏原版玩家模型的某一个部分,并将隐藏的模型部分ID填到hidden里,一般初始形态都不隐藏,四足形态全部隐藏,在furs文件介绍中示例为全部隐藏。

    3. 编写 tail_chain tail_chain_head wing_chain_l wing_chain_r 具体在furs文件介绍,一般在BlockBench模型分组名字中含有tail或wing的骨骼。

    4. 如果有皮肤覆盖材质(overlay) 把图片路径填到overlay上,Mod在悦灵和赤狐形态中使用此功能。

    5. 如果有 texture_mask overlay_mask 将路径填到furs中,具体mask如何实现在下文中说明。

  6. 为形态添加文本 具体看文件介绍中lang和rich_lang。



数据包部分

  1. 创建一个数据包文件夹,编写pack.mcmeta 介绍在数据包 - 中文 Minecraft Wiki

  2. 编写能力文件,放置在data_pack/data/example_namespace/powers/文件夹下 具体可以起源里面的官方Wiki或页面下的Mod教程。

  3. 编写起源数据文件,放置在data_pack/data/example_namespace/origins/文件夹下,具体教程同上,或者看上面的文件介绍中的origins。

  4. 编写形态定义文件,放置在data_pack/data/example_namespace/ssc_form/文件夹下,具体项看上面的文件介绍中的ssc_form,下面是一些注意事项。

    - 每个形态都必须包含一个形态scale能力,实现在下文中说明。

    - 形态定义文件的文件名就是形态ID的Path,如果originID使用默认值时,修改必须同时修改origins里的文件名。

    - 编写动作时的ID为动作文件json内部ID而不是文件名,填错会因为找不到动画使用原版动作,这种情况不会使用默认动作(animDefault)。 作者之前制作样例只修改文件名导致四足形态直接直立行走

    - 极度不推荐修改 originLayerID 会导致模型异常。

  5. 编写变形能力,并使用origins_power_extra挂载到某一形态上,变形能力的实现在下文中说明。

  6. 将起源注册到data_pack/data/origins/origin_layer/origin.json 具体项看上面的文件介绍中的origin_layers/origin.json。




额外介绍项

Mask系统 实现玩家自定义形态颜色

Wiki文档

Mask图片中 R(红)通道用来说明对应位置的材质需要用主要色填充,G(绿)为重点色1, B(蓝)为重点色2,A(透明度)用于区分一些特殊位置,A通道1为眼睛A、2为眼睛B,一般眼睛A为右眼,眼睛B为左眼(贴图上眼睛A在左边,眼睛B在右边)。

覆盖顺序(从左往右 左边覆盖右边) A特殊像素 > B重点色2 > G重点色2 > R主要色。

具体的颜色计算请看源码中FormTextureUtils里的ProcessPixel。

支持仅使用正片叠底渲染自定义颜色,需要在furs文件IsMultiplyMask项设置为true,使用此功能时需要把亮度烘焙到对应Mask通道中。



变形能力系统 实现不使用药水效果的变形逻辑

变形能力具体由shape-shifter-curse:transform_to_form这个实体Action驱动。

使用Action的能力可以看 Origins的官方Wiki 中的Action-related项。

变形Action(shape-shifter-curse:transform_to_form)中form_id为目标形态ID,instant为true时会瞬间变形(同命令set_form)否则播放变身动画。



本能值系统

Mod中本能值由 add_immediate_instinct(立即添加本能 类型为Power) add_sustained_instinct(持续添加本能 类型为Power) add_instinct(添加本能 类型为Action) 三种添加方式。

具体可用值

instinct_effect_id 添加本能效果ID,后应用的添加本能值会覆盖掉同ID的正在生效的效果。

value 本能每Tick增加量(支持负数)。

duration 持续时长,仅add_sustained_instinct和add_instinct可用。



形态scale能力

样例:

{
  "type": "shape-shifter-curse:scale",
  "scale": 0.5,
  "eye_scale": 0.6
}

scale 为整体碰撞箱缩放,随模型变化而变化。

eye_scale 为眼部高度缩放,通常正常形态为1.0,四足形态为0.6,蝙蝠最终形态为0.6。

还有一种条件性修改scale的能力 Mod中仅用于豹猫第3阶段(ocelot_2)

样例: (ocelot_2形态当玩家蹲下时修改eye_scale为0.6)

{
    "type": "shape-shifter-curse:condition_scale",
    "scale": 0.65,
    "eye_scale": 0.6,
    "original_scale": 0.65,
    "original_eye_scale": 1.0,
    "condition": {
        "type": "origins:and",
        "conditions": [
            {
                "type": "origins:sneaking"
            }
        ]
    }
}

original_scale 和 original_eye_scale 必须和形态基础scale能力对应值相等,否则会无法还原scale。


修改物品可食用能力

样例: (可以吃紫水晶碎片的能力 吃完后获得10s力量2)

{
    "type": "shape-shifter-curse:custom_edible",
    "item_id_list": [
        "minecraft:amethyst_shard"
    ],
    "hunger": 10,
    "saturation_modifier": 0.3,
    "always_edible": true,
    "status_effects": [
        {
            "effect": "minecraft:strength",
            "duration": 200,
            "amplifier": 1,
            "show_particles": false,
            "show_icon": true
        }
    ]
}

item_id_list 物品ID列表,在这个列表中所有物品ID均会可食用。

hunger 饱食度,食用物品后恢复多少饱食度。

saturation_modifier 饱和度比例,食用物品后按多少比例添加饱和度。

meat 是否为肉类。

always_edible 是否在饱食度满时食用物品。

snack 是否为小吃,如果为小吃会比其他食物吃的快一些(参考干海带的速度)

status_effects 食用后获得的状态效果。



结束语

感谢你看完了我的这篇教程,这是我的第一篇教程,如果有错误就请说明,我会马上修改。如果有关于这个Mod的Bug或想法,可以在Github上写issues或者在教程下评论,我看见会回复的。

由于现在这个Mod开发没有专门的全方面的测试流程(通常仅会测试修改部分),已经需要连续发布紧急Bug修复版本(1.0.75、1.0.76)Bug点还是同一个函数。现在发布新版本时会提前发布测试版(在Github Action里下载),如果没有Bug就会发布正式版。

如果有时间和能力测试的,可以在Github Action里下载测试版并在issues里提交Bug,帮助这个Mod变得更好。


这个Mod现在可以使用信雅互联来让Forge端运行Mod(感谢donmor提供的方法),需要额外安装Github上的Apoli 2.9.2(Fabric)版本,搭配Connector Extras就可以运行官方版本(1.0.73)或非官方兼容版(1.0.75 版本目录 但修复了导致1.0.76更新的主要Bug其实没有主动修 只不过要兼容互联就把那部分代码重构了)。