Files
netease-modsdk-wiki/docs/wiki/items/spear.md
2025-03-20 11:52:46 +08:00

12 KiB
Raw Blame History

title, category, tags, mentions, hidden
title category tags mentions hidden
自定义长矛 巧思案例
脚本
XxPoggyisLitxX
SirLich
TheItsNamless
ThomasOrs
kumja1
true

自定义长矛

::: tip 强烈建议您对JavaScript和Script-API有基本的了解。 :::

::: warning 请确保已为本教程准备好基础纹理和模型。 :::

开始前,请确认文件结构已正确设置:

<FolderView :paths="[ 'com.mojang/development_resource_packs/spear_RP/textures/items/spear.png', 'com.mojang/development_resource_packs/spear_RP/textures/entities/spear.png', 'com.mojang/development_resource_packs/spear_RP/entities/spear.json', 'com.mojang/development_resource_packs/spear_RP/attachables/spear.json', 'com.mojang/development_resource_packs/spear_RP/animations/spear_animation.json', 'com.mojang/development_resource_packs/spear_RP/texts/en_US.lang', 'com.mojang/development_resource_packs/spear_RP/manifest.json', 'com.mojang/development_resource_packs/spear_RP/pack_icon.png', 'com.mojang/development_behavior_packs/spear_BP/items/spear.json', 'com.mojang/development_behavior_packs/spear_BP/entities/spear.json', 'com.mojang/development_behavior_packs/spear_BP/pack_icon.png', 'com.mojang/development_behavior_packs/spear_BP/manifest.json' ]"

制作自定义长矛其实非常简单不过对Koala Boy来说可不简单。虽然涉及部分脚本但核心行为并不依赖脚本实现。

物品

首先需要创建长矛物品,但这里不使用"基础"行为组件。我们通过以下组件实现特殊功能:

::: code-group

{
    //使用持续时间是我们能使用物品的最长时间
    "minecraft:use_duration": 3600,
    //赋予长矛类似弓的拉弓能力
    "minecraft:throwable": {
        "min_draw_duration": 2,
        "max_draw_duration": 4,
        "scale_power_by_draw_duration": true
    },
    //完成蓄力后发射的抛射物
    "minecraft:projectile": {
        "projectile_entity": "wiki:thrown_iron_spear",
        "minimum_critical_power": 1.0
    },
    //长矛耐久度
    "minecraft:durability": {
        "max_durability": 125
    }
}

:::

抛射物实体

接下来创建抛射物实体。该实体需要特殊组件和运行时标识符来实现正确行为:

::: code-group

{
    "format_version": "1.12.0",
    "minecraft:entity": {
        "description": {
            "identifier": "wiki:thrown_iron_spear",
            "is_spawnable": false,
            "is_summonable": true,
            "is_experimental": false,
            "runtime_identifier": "minecraft:snowball"
        },
        "component_groups": {
            "wiki:give": {
                "minecraft:instant_despawn": {}
            }
        },
        "components": {
            "minecraft:conditional_bandwidth_optimization": {
                "default_values": {
                    "max_dropped_ticks": 10,
                    "max_optimized_distance": 100,
                    "use_motion_prediction_hints": true
                }
            },
            "minecraft:hurt_on_condition": {
                "damage_conditions": [
                    {
                        "cause": "lava",
                        "damage_per_tick": 4,
                        "filters": {
                            "operator": "==",
                            "subject": "self",
                            "test": "in_lava",
                            "value": true
                        }
                    }
                ]
            },
            "minecraft:physics": {},
            "minecraft:projectile": {
                "anchor": 1,
                "gravity": 0.05,
                "hit_sound": "bow.hit",
                "offset": [
                    0,
                    -0.1,
                    0
                ],
                "on_hit": {
                    "definition_event": {
                        "event_trigger": {
                            "event": "example:foo",
                            "target": "self"
                        }
                    },
                    "impact_damage": {
                        "damage": 7,
                        "destroy_on_hit": false,
                        "knockback": true,
                        "power_multiplier": 0.97,
                        "semi_random_diff_damage": false
                    },
                    "stick_in_ground": {
                        "shake_time": 0.35
                    }
                },
                "power": 3,
                "should_bounce": true,
                "stop_on_hurt": true
            },
            "minecraft:pushable": {
                "is_pushable": false,
                "is_pushable_by_piston": true
            }
        }
    }
}

:::

现在需要添加玩家拾取机制。通过实体传感器和事件实现:

::: code-group

{
    "components": {
        //实体传感器检测抛射物是否在地面上,以及玩家是否靠近实体
        //当条件满足时触发事件
        "minecraft:entity_sensor": {
            "event": "wiki:give",
            "event_filters": {
                "all_of": [
                    {
                        "subject": "other",
                        "test": "is_family",
                        "value": "player"
                    },
                    {
                        "subject": "self",
                        "test": "on_ground",
                        "value": true
                    }
                ]
            },
            "minimum_count": 1,
            "relative_range": false,
            "sensor_range": 0.7
        }
    },
    "events": {
        /*
        该事件会立即销毁抛射物,并给玩家添加标签(将在脚本中使用)
        */
        "wiki:give": {
            "sequence": [
                {
                    "add": {
                        "component_groups": [
                            "wiki:give"
                        ]
                    }
                },
                {
                    "randomize": [
                        {
                            "run_command": {
                                "command": [
                                    "playsound random.pop @p",
                                    "tag @p add iron_spear"
                                ]
                            },
                            "weight": 90
                        }
                    ]
                }
            ]
        }
    }
}

:::

客户端实体

为抛射物创建客户端实体文件:

::: code-group

{
    "format_version": "1.10.0",
    "minecraft:client_entity": {
        "description": {
            "identifier": "wiki:thrown_iron_spear",
            "materials": {
                "default": "entity_alphatest"
            },
            "textures": {
                "default": "textures/entity/iron_spear"
            },
            "animations": {
                "move": "animation.weapon.default_thrown"
            },
            "scripts": {
                "animate": [
                    "move"
                ]
            },
            "geometry": {
                "default": "geometry.stone_spear"
            },
            "render_controllers": [
                "controller.render.default"
            ]
        }
    }
}

:::

:::warning 请确保实体模型符合下图样式! :::

动画

使用Molang实现抛射物飞行时的旋转动画:

::: code-group

{
	"format_version": "1.8.0",
	"animations": {
		"animation.weapon.default_thrown": {
			"loop": true,
			"bones": {
				"body": {
                    //这是一些molang代码。动画根据当前角度旋转模型
					"rotation": ["-q.target_x_rotation", "-q.body_y_rotation", 0]
				}
			}
		}
    }
}

:::

附着物

使用三叉戟的附着物模板,已包含持握动画:

::: code-group

{
    "format_version": "1.10.0",
    "minecraft:attachable": {
        "description": {
            "identifier": "wiki:iron_spear",
            "materials": {
                "default": "entity_alphatest",
                "enchanted": "entity_alphatest_glint"
            },
            "textures": {
                "default": "textures/entity/iron_spear",
                "enchanted": "textures/misc/enchanted_item_glint"
            },
            "geometry": {
                "default": "geometry.stone_spear_item"
            },
            "animations": {
                "wield": "controller.animation.trident.wield",
                "wield_first_person": "animation.trident.wield_first_person",
                "wield_first_person_raise": "animation.trident.wield_first_person_raise",
                "wield_first_person_raise_shake": "animation.trident.wield_first_person_raise_shake",
                "wield_first_person_riptide": "animation.trident.wield_first_person_riptide",
                "wield_third_person": "animation.trident.wield_third_person",
                "wield_third_person_raise": "animation.trident.wield_third_person_raise"
            },
            "scripts": {
                "pre_animation": [
                    "v.charge_amount = math.clamp((q.main_hand_item_max_duration - (q.main_hand_item_use_duration - q.frame_alpha + 1.0)) / 10.0, 0.0, 1.0f);"
                ],
                "animate": [
                    "wield"
                ]
            },
            "render_controllers": [
                "controller.render.item_default"
            ]
        }
    }
}

:::

脚本

通过Script-API实现耐久度消耗

import { world, ItemStack } from "@minecraft/server"
import { system } from "@minecraft/server";
//防止世界崩溃
system.beforeEvents.watchdogTerminate.subscribe(data => {
  data.cancel = true;
});

world.afterEvents.itemReleaseUse.subscribe(ev => {
    //多人游戏支持
    for (const player of world.getPlayers()){
      let inv = player.getComponent( 'inventory' ).container
      //保存物品数据
      const itemStack = inv.getItem(player.selectedSlot);
      //检测是否持有长矛
      if (itemStack?.typeId === 'wiki:iron_spear') {
        var container = player.getComponent('inventory').container
        var newItem =  new ItemStack("wiki:iron_spear");
        var oldItem = container?.getItem(player.selectedSlot)
        player.removeTag("iron_spear")
        }
        //Tick事件检测标签和耐久度
      let e = system.runInterval(() => {
      if(player.hasTag("iron_spear") && itemStack?.typeId === 'wiki:iron_spear' && itemStack?.getComponent("durability").damage <= 125) {
        player.removeTag("iron_spear")
        //拾取时增加耐久损耗
        newItem.getComponent("durability").damage = oldItem.getComponent("durability").damage + 1;
        container.setItem(player.selectedSlot, newItem);
        //清除Tick事件
        if(!player.hasTag("iron_spear")){
        system.clearRun(e);
      }}
    })}
    })

最终效果

完成所有步骤后,即可在游戏中获得可正常使用的长矛:

示例包下载:

<BButton link="https://github.com/Bedrock-OSS/wiki-addon/releases/download/download/custom_spear.mcaddon" color=blue

💾 示例包