Page MenuHome1F616EMO Bugtracker

No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None
diff --git a/README.md b/README.md
index c58f3a5..14ccfce 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,28 @@
# Guider
API for creating waypoints that fire callbacks on player approach. Useful for quests management, etc.
## API
* `guider.add_waypoint(player, def)`: Create a waypoint for a player. Returns a handler.
* `guider.destroy_waypoint(player, handler)`: Destructs a waypoint by the player object and the handler.
## Waypoint definition
```lua
{
name = "Display Name", -- string, optional, default: stringified position
image = "guider_marker_default.png", -- string, optional, default: guider_marker_default.png
suffix = " m", -- string, optional, default: none
percision = 10, -- integer >= 0, optional, default: 10 (1 d.p.)
text_color = 0xffffff, -- integer of color, optional, default: 0xffffff (white)
scale = { x = 2, y = 2 }, -- image scale in table (x, y) or number, optional, default: 2
image_height = 16, -- image height in pixel, optional, default: 16
pos = vector.new(0, 0, 0), -- posiiton of waypoint, mandantory
on_approach = function(player, handler) end, -- Called on approach, optional
approach_distance = 5, -- Maximum distance to be considered approaching, optional
+ max_age = 60, -- Maximum age in seconds, optional, default: infinity
}
```
Both `on_approach` and `approach_distance` must be set for approach detection to work.
diff --git a/init.lua b/init.lua
index 5d7e958..34db03b 100644
--- a/init.lua
+++ b/init.lua
@@ -1,172 +1,181 @@
-- guider/init.lua
-- HUD markers for navigation
-- Copyright (C) 2025 1F616EMO
-- SPDX-License-Identifier: LGPL-3.0-or-later
guider = {}
-- player name: handler: data
guider.markers_by_player_name = {}
function guider.destroy_waypoint(player, handler)
assert(player and player.is_player and player:is_player(), "Non-player object passed into guider.add_waypoint")
local name = player:get_player_name()
local player_data = guider.markers_by_player_name[name]
local data = player_data and player_data[handler]
if not data then return false end
player:hud_remove(data.text_hud_id)
player:hud_remove(data.image_hud_id)
player_data[handler] = nil
if not next(player_data) then
guider.markers_by_player_name[name] = nil
end
return true
end
function guider.add_waypoint(player, def)
assert(player and player.is_player and player:is_player(), "Non-player object passed into guider.add_waypoint")
assert(type(def) == "table", "Invalid type of def (table expected, got " .. type(def) .. ")")
assert(type(def.name) == "string" or def.name == nil,
"Invalid type of def.name (string or nil expected, got " .. type(def.name) .. ")")
assert(type(def.image) == "string" or def.image == nil,
"Invalid type of def.image (string or nil expected, got " .. type(def.image) .. ")")
assert(type(def.suffix) == "string" or def.suffix == nil,
"Invalid type of def.suffix (string or nil expected, got " .. type(def.suffix) .. ")")
assert(type(def.percision) == "number" or def.percision == nil,
"Invalid type of def.percision (number or nil expected, got " .. type(def.percision) .. ")")
assert(type(def.text_color) == "number" or def.text_color == nil,
"Invalid type of def.text_color (number or nil expected, got " .. type(def.text_color) .. ")")
assert(type(def.scale) == "number" or type(def.scale) == "table" or def.scale == nil,
"Invalid type of def.scale (number, table or nil expected, got " .. type(def.scale) .. ")")
assert(type(def.image_height) == "number" or def.image_height == nil,
"Invalid type of def.image_height (number or nil expected, got " .. type(def.image_height) .. ")")
assert(type(def.pos) == "table", "Invalid type of def.pos (table expected, got " .. type(def.pos) .. ")")
assert(type(def.pos.x) == "number", "Invalid type of def.pos.x (number expected, got " .. type(def.pos.x) .. ")")
assert(type(def.pos.y) == "number", "Invalid type of def.pos.y (number expected, got " .. type(def.pos.y) .. ")")
assert(type(def.pos.z) == "number", "Invalid type of def.pos.z (number expected, got " .. type(def.pos.z) .. ")")
assert(type(def.on_approach) == "function" or def.on_approach == nil,
"Invalid type of def.on_approach (function or nil expected, got " .. type(def.on_approach) .. ")")
assert(type(def.approach_distance) == "number" or def.approach_distance == nil,
"Invalid type of def.approach_distance (number or nil expected, got " .. type(def.approach_distance) .. ")")
+ assert(type(def.max_age) == "number" or def.max_age == nil,
+ "Invalid type of def.max_age (number or nil expected, got " .. type(def.max_age) .. ")")
if def.scale == nil then
def.scale = { x = 2, y = 2 }
elseif type(def.scale) == "number" then
def.scale = { x = def.scale, y = def.scale }
end
local data = {}
data.text_hud_id = player:hud_add({
type = "waypoint",
name = def.name or core.pos_to_string(def.pos, 0),
text = def.suffix or "",
precision = def.percision or 10,
number = def.text_color or 0xffffff,
world_pos = def.pos,
offset = {x = 0, y = def.scale.y * (def.image_height or 16) * -1 - 7},
z_index = -300,
})
data.image_hud_id = player:hud_add({
type = "image_waypoint",
scale = def.scale,
text = def.image or "guider_marker_default.png",
world_pos = def.pos,
z_index = -300,
})
data.def = def
+ data.created_on = os.time()
local name = player:get_player_name()
guider.markers_by_player_name[name] = guider.markers_by_player_name[name] or {}
local handler = 1
while guider.markers_by_player_name[name][handler] do
handler = handler + 1
end
guider.markers_by_player_name[name][handler] = data
return handler
end
do
local passed = 0.1
core.register_globalstep(function(dtime)
passed = passed + dtime
if passed < 0.3 then
return
end
passed = 0
+ local now = os.time()
+
for _, player in ipairs(core.get_connected_players()) do
local name = player:get_player_name()
local pos = player:get_pos()
local player_data = guider.markers_by_player_name[name]
for handler, data in pairs(player_data or {}) do
if data.def.approach_distance and data.def.on_approach then
if vector.distance(pos, data.def.pos) <= data.def.approach_distance then
core.after(0, data.def.on_approach, player, handler)
end
end
+
+ if data.def.max_age and (data.created_at + data.def.max_age > now) then
+ guider.destroy_waypoint(player, handler)
+ end
end
end
end)
end
core.register_on_leaveplayer(function(player)
local name = player:get_player_name()
guider.markers_by_player_name[name] = nil
end)
core.register_chatcommand("guider_test_waypoint", {
privs = { server = true },
description = "Test Guider Waypoints: Create a waypoint at (0, 0, 0)",
param = "[<waypoint name>]",
func = function(name, param)
local player = core.get_player_by_name(name)
if not player then
return false, "This command can only be executed when you're online."
end
if param == "" then
param = nil
end
local handler = guider.add_waypoint(player, {
name = param,
suffix = " m",
pos = vector.new(0, 0, 0),
approach_distance = 5,
on_approach = guider.destroy_waypoint,
})
return true, "Created a waypoint with handler: " .. tostring(handler) ..
". Use /guider_test_waypoint_destruct " .. tostring(handler) .. " to remove it."
end,
})
core.register_chatcommand("guider_test_waypoint_destruct", {
privs = { server = true },
description = "Test Guider Waypoints: Destruct a waypoint with the given handler.",
param = "<waypoint handler>",
func = function(name, param)
local player = core.get_player_by_name(name)
if not player then
return false, "This command can only be executed when you're online."
end
local handler = tonumber(param)
if guider.destroy_waypoint(player, handler) then
return true, "Successfully destroyed waypoint with handler " .. param .. "."
else
return false, "Failed to destroy waypoint with handler " .. param .. "."
end
end,
})

File Metadata

Mime Type
text/x-diff
Expires
Thu, Mar 5, 7:38 AM (1 d, 13 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
24/7c/0141e7fdd408245f75c83ec431f0
Default Alt Text
(8 KB)

Event Timeline