Page Menu
Home
1F616EMO Bugtracker
Search
Configure Global Search
Log In
Files
F156152
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Feb 27, 6:09 PM (4 d, 8 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
24/7c/0141e7fdd408245f75c83ec431f0
Default Alt Text
(8 KB)
Attached To
Mode
rMODGUIDER Guider
Attached
Detach File
Event Timeline
Log In to Comment