--- title: 自定义长矛 category: 巧思案例 tags: - 脚本 mentions: - XxPoggyisLitxX - SirLich - TheItsNamless - ThomasOrs - kumja1 hidden: true --- # 自定义长矛 ::: tip 强烈建议您对JavaScript和Script-API有基本的了解。 ::: ::: warning 请确保已为本教程准备好基础纹理和模型。 ::: 开始前,请确认文件结构已正确设置: 制作自定义长矛其实非常简单(不过对Koala Boy来说可不简单)。虽然涉及部分脚本,但核心行为并不依赖脚本实现。 ## 物品 首先需要创建长矛物品,但这里不使用"基础"行为组件。我们通过以下组件实现特殊功能: ::: code-group ```json [BP/items/spear.json] { //使用持续时间是我们能使用物品的最长时间 "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 ```json [BP/entities/spear.json] { "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 ```json [BP/entities/spear.json] { "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 ```json [RP/entities/spear.json] { "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 请确保实体模型符合下图样式! ::: ![](/assets/images/items/spears/spear_model.png) ## 动画 使用[Molang](https://bedrock.dev/docs/stable/Molang)实现抛射物飞行时的旋转动画: ::: code-group ```json [BP/animations/spear.json] { "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 ```json [BP/attachables/spear.json] { "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实现耐久度消耗: ```js 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); }} })} }) ``` ## 最终效果 完成所有步骤后,即可在游戏中获得可正常使用的长矛: ![](/assets/images/items/spears/spear_first_person.png) ![](/assets/images/items/spears/spear_third_person.png) 示例包下载: 💾 示例包