跳至正文
版本:最新版 - a1.148.0 ⚖️

工具枪

如何为 nanos world 创建新的工具枪

信息

这种工具枪方案是沙盒游戏模式的一种约定,并非全局游戏概念。

沙盒游戏模式定义了一个 ToolGun 类(在 GitHub 上查看:服务器客户端),有助于基于基础工具枪创建新工具。

创建自定义工具枪

要基于沙盒的 ToolGun 创建你自己的工具,你需要创建一个继承自它的新类,并向该类传递一些自定义参数,如下所示:

MyToolGun = ToolGun.Inherit("MyToolGun", {
-- 生成菜单
name = "我的工具枪",
image = "package://my-package/MyToolGun.webp",
category = "special",

-- 将在左上方显示的工具枪描述
description = "施展魔法!",

-- 将在左上方显示的工具枪教程
tutorials = {
{ key = "LeftClick", text = "生成我的实体" },
{ key = "Undo", text = "撤销生成" },
{ key = "ContextMenu", text = "生成设置" },
},

-- 每 1 分钟作为通知显示的工具枪提示
tips = {
"你可以使用此工具枪来做些酷炫的事情!",
"注意不要玩得太嗨过头!"
},

-- 工具枪射线检测调试设置,在使用此工具枪瞄准时会在世界中显示
debug_trace = {
-- 定义使用此工具枪射击时要检测的碰撞通道 (Collision Channel)
collision_channel = CollisionChannel.WorldStatic | CollisionChannel.WorldDynamic | CollisionChannel.PhysicsBody | CollisionChannel.Vehicle,

-- 瞄准时工具枪是否应在检测结果上显示准星
show_crosshair = false,

-- 瞄准时工具枪是否应在检测结果上显示预览网格体 (Preview Mesh)
show_preview_mesh = true,

-- 预览网格体配置
preview_mesh = "nanos-world::SM_Toaster",
preview_mesh_scale = Vector(1, 1, 1),
preview_mesh_offset = Vector(0, 0, 0),
preview_mesh_rotation = Rotator(0, 0, 0),
preview_mesh_rotation_fixed = false
}
})
提示

nameimagecategory 的值供生成菜单使用,以便在菜单中正确显示。

其他值(如 tutorialsdebug_trace)由 ToolGun 使用,用于在使用它时添加自定义教程或行为。 这些参数是可选的。

这些值仅在客户端使用!

你还可以通过在工具枪类上定义 picked_context_menu_items 表,为你的工具枪在上下文菜单中添加自定义条目。当你捡起工具枪并打开上下文菜单时,这些配置就会出现:

Client/Index.lua
-- 定义自定义工具枪值的初始值
MyToolGun.my_custom_value = 123

-- 我的工具枪上下文菜单回调函数
function MyToolGun.SetMyCustomValue(value)
MyToolGun.my_custom_value = value

-- 你可以在这里对这个值进行操作,
-- 比如调用远程事件来通知服务端
end

-- 将在上下文菜单中显示的工具枪上下文菜单条目
MyToolGun.picked_context_menu_items = {
{
id = "my_tool_gun_custom_value",
type = "number",
label = "自定义值",
callback = MyToolGun.SetMyCustomValue,
value = MyToolGun.my_custom_value
},
},
提示

你可以参阅上下文菜单文档页面了解如何配置上下文菜单项。

重写工具枪客户端方法

ToolGun 在客户端有一些方法,你可以重写这些方法,以便在本地玩家与其交互时为工具实现自定义行为。

你只需在自定义工具枪类中重写它们即可实现:

Client/Index.lua
-- 当你使用它开火时调用
function MyToolGun:OnLocalPlayerFire(character)
-- 执行某些操作

-- 这里很有用的做法是检测玩家射击的位置,
-- 并将该坐标发送到服务端,以便在该位置生成物体
end

-- 当你捡起它时调用
function MyToolGun:OnLocalPlayerPickUp(character)
-- 执行某些操作

-- 比如启动某种效果或计算
end

-- 当你丢弃它时调用
function MyToolGun:OnLocalPlayerDrop(character)
-- 执行某些操作

-- 丢弃工具时,你很可能需要禁用任何效果或类似的东西
end

工具枪单目标与双目标

我们实现了 ToolGun 的两个子类,分别称为 ToolGunSingleTargetToolGunDoubleTarget,它们提供了一些额外功能,使创建在开火时需要一个或两个目标的工具枪变得更加简单。

ToolGunSingleTarget

当你想要创建一个在开火时只需要一个目标的工具枪时(例如在射击时于检测位置生成实体的工具枪),此类非常有用。

它使实现变得非常容易,因为你只需重写 OnLocalPlayerTarget 方法,在使用工具枪开火时该方法将携带检测结果被调用,因此你只需将该坐标发送到服务器以在该位置生成物体即可。

Client/Index.lua
MyToolGun = ToolGunSingleTarget.Inherit("MyToolGun")

-- 重写 ToolGunSingleTarget 方法
function MyToolGun:OnLocalPlayerTarget(location, relative_location, relative_rotation, normal, entity)
-- 调用远程事件以在该位置生成物品
self:CallRemoteEvent("SpawnSomething", Reliability.Reliable, location, relative_location, relative_rotation, normal, entity)
end

ToolGunDoubleTarget

当你想要创建一个开火时需要两个目标的工具枪时(例如将两个实体焊接在一起的工具枪),此类非常有用。

你可以重写 OnLocalPlayerTarget 方法,该方法仅在两个目标都已设置时才会被调用,因此你只需将这两个坐标发送到服务端对其执行相应操作即可。

Client/Index.lua
MyToolGun = ToolGunDoubleTarget.Inherit("MyToolGun")

-- 重写 ToolGunDoubleTarget 方法
function MyToolGun:OnLocalPlayerTarget(targeting_first_to, targeting_first_relative_location, targeting_first_relative_rotation, targeting_second_to, targeting_second_location, targeting_second_rotation)
-- 调用远程事件将两个实体焊接在一起
self:CallRemoteEvent("Weld", Reliability.Reliable, targeting_first_to, targeting_second_to, targeting_second_location)
end

示例

你可以在沙盒的 Tools/ 文件夹中找到更多工具示例(包含客户端服务端)。

现在轮到你来创建带有你专属工具的包了!