174 lines
5.4 KiB
Lua
174 lines
5.4 KiB
Lua
|
--
|
|||
|
-- Ptolomey King Protector
|
|||
|
-- License:GPLv3
|
|||
|
--
|
|||
|
local modname = minetest.get_current_modname()
|
|||
|
local S = minetest.get_translator(modname)
|
|||
|
local modpath = minetest.get_modpath(modname)
|
|||
|
local ptol = {}
|
|||
|
ptol.settings = {}
|
|||
|
ptol.players = {}
|
|||
|
ptol.warnings = {}
|
|||
|
local static_spawnpoint = minetest.setting_get_pos("static_spawnpoint")
|
|||
|
|
|||
|
--Settings
|
|||
|
|
|||
|
local settings = Settings(modpath .. "/ptol.conf")
|
|||
|
ptol.settings.radius = tonumber(settings:get("radius")) or 120
|
|||
|
ptol.settings.world_center = minetest.string_to_pos(settings:get("world_center")) or static_spawnpoint or {x=0, y=0, z=0}
|
|||
|
ptol.settings.allowed_angle = tonumber(settings:get("allowed_angle")) or 45
|
|||
|
ptol.settings.time = tonumber(settings:get("time")) or 1
|
|||
|
|
|||
|
local function player_inside_sphere(player_pos, ptol_level)
|
|||
|
player_pos.y = player_pos.y - 1
|
|||
|
--If sphere's centre coordinates is (cx,cy,cz) and its radius is r,
|
|||
|
--then point (x,y,z) is in the sphere if (x−cx)2+(y−cy)2+(z−cz)2<r2.
|
|||
|
local distance_to_center = math.sqrt((player_pos.x - ptol.settings.world_center.x)^2+
|
|||
|
(player_pos.y - ptol.settings.world_center.y)^2 +
|
|||
|
(player_pos.z - ptol.settings.world_center.z)^2)
|
|||
|
--minetest.chat_send_all(tostring(ptol_level))
|
|||
|
if (ptol.settings.radius * ptol_level) >= distance_to_center then
|
|||
|
return true
|
|||
|
else
|
|||
|
return false
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--Freeze Player Code
|
|||
|
|
|||
|
function ptol.is_frozen(player)
|
|||
|
return ptol.players[player:get_player_name()]
|
|||
|
end
|
|||
|
|
|||
|
minetest.register_entity("ptol:freeze", {
|
|||
|
-- This entity needs to be visible otherwise the frozen player won't be visible.
|
|||
|
initial_properties = {
|
|||
|
visual = "sprite",
|
|||
|
visual_size = { x = 0, y = 0 },
|
|||
|
textures = {"ptol_blank.png"},
|
|||
|
physical = false, -- Disable collision
|
|||
|
pointable = false, -- Disable selection box
|
|||
|
makes_footstep_sound = false,
|
|||
|
},
|
|||
|
|
|||
|
on_step = function(self, dtime)
|
|||
|
local player = self.pname and minetest.get_player_by_name(self.pname)
|
|||
|
if not player or not ptol.is_frozen(player) then
|
|||
|
self.object:remove()
|
|||
|
return
|
|||
|
end
|
|||
|
end,
|
|||
|
|
|||
|
set_frozen_player = function(self, player)
|
|||
|
self.pname = player:get_player_name()
|
|||
|
player:set_attach(self.object, "", {x = 0, y = 0, z = 0 }, { x = 0, y = 0, z = 0 })
|
|||
|
end,
|
|||
|
})
|
|||
|
|
|||
|
function ptol.freeze(player)
|
|||
|
ptol.players[player:get_player_name()] = true
|
|||
|
local parent = player:get_attach()
|
|||
|
if parent and parent:get_luaentity() and
|
|||
|
parent:get_luaentity().set_frozen_player then
|
|||
|
-- Already attached
|
|||
|
return
|
|||
|
end
|
|||
|
local obj = minetest.add_entity(player:get_pos(), "ptol:freeze")
|
|||
|
obj:get_luaentity():set_frozen_player(player)
|
|||
|
end
|
|||
|
|
|||
|
function ptol.unfreeze(player)
|
|||
|
ptol.players[player:get_player_name()] = nil
|
|||
|
local pname = player:get_player_name()
|
|||
|
local objects = minetest.get_objects_inside_radius(player:get_pos(), 2)
|
|||
|
for i=1, #objects do
|
|||
|
local entity = objects[i]:get_luaentity()
|
|||
|
if entity and entity.set_frozen_player and entity.pname == pname then
|
|||
|
objects[i]:remove()
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function ptol.show_warning(player)
|
|||
|
local hud_id = player:hud_add({
|
|||
|
hud_elem_type = "text",
|
|||
|
position = {x = 0.5, y = 0.5},
|
|||
|
offset = {x = 0, y = 0},
|
|||
|
text = S("You have reached the limits of your world.\nTurn around and go back where you came from."),
|
|||
|
alignment = {x = 0, y = 0}, -- center aligned
|
|||
|
scale = {x = 100, y = 100}, -- covered later
|
|||
|
})
|
|||
|
ptol.warnings[player:get_player_name()] = hud_id
|
|||
|
end
|
|||
|
|
|||
|
function ptol.remove_warning(player)
|
|||
|
player:hud_remove(ptol.warnings[player:get_player_name()])
|
|||
|
end
|
|||
|
|
|||
|
local timer = 0
|
|||
|
|
|||
|
minetest.register_globalstep(function(dtime)
|
|||
|
timer = timer + dtime
|
|||
|
if timer <= ptol.settings.time then
|
|||
|
return
|
|||
|
end
|
|||
|
timer = 0
|
|||
|
for _, player in pairs(minetest.get_connected_players()) do
|
|||
|
local player_pos = player:get_pos()
|
|||
|
local ptol_level = player:get_meta():get_int("ptol:level")
|
|||
|
if ptol_level == 0 then
|
|||
|
ptol_level = 1
|
|||
|
end
|
|||
|
--minetest.chat_send_all(tostring(ptol_level))
|
|||
|
if not player_inside_sphere(player_pos, ptol_level) then
|
|||
|
local dir_to_center = vector.direction(player_pos, ptol.settings.world_center)
|
|||
|
local player_dir = player:get_look_dir()
|
|||
|
local angle_to_center = math.deg(vector.angle(dir_to_center, player_dir))
|
|||
|
--minetest.chat_send_all(tostring(angle_to_center))
|
|||
|
local frozen = ptol.is_frozen(player)
|
|||
|
--minetest.chat_send_all(tostring(angle_to_center)..":"..tostring(ptol.settings.allowed_angle))
|
|||
|
if not(frozen) and (angle_to_center > ptol.settings.allowed_angle) then
|
|||
|
ptol.freeze(player)
|
|||
|
ptol.show_warning(player)
|
|||
|
minetest.sound_play("ptol_warning", {to_player = player:get_player_name(), gain = 1.0, max_hear_distance = 10,})
|
|||
|
--minetest.chat_send_all("freeze")
|
|||
|
elseif frozen and ((angle_to_center <= ptol.settings.allowed_angle)) then
|
|||
|
ptol.unfreeze(player)
|
|||
|
ptol.remove_warning(player)
|
|||
|
--minetest.chat_send_all("unfreeze")
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end)
|
|||
|
|
|||
|
--COMMANDS
|
|||
|
|
|||
|
minetest.register_chatcommand("ptol", {
|
|||
|
privs = {
|
|||
|
server = true,
|
|||
|
},
|
|||
|
description = "Ptolomey Commands",
|
|||
|
func = function(name, param)
|
|||
|
local player_name, value
|
|||
|
local i = 0
|
|||
|
for word in string.gmatch(param, "([%a%d_-]+)") do
|
|||
|
if i == 0 then
|
|||
|
player_name = word
|
|||
|
else
|
|||
|
value = word
|
|||
|
end
|
|||
|
i = i + 1
|
|||
|
end
|
|||
|
local player = minetest.get_player_by_name(player_name)
|
|||
|
if not player then
|
|||
|
return true, "Error: The player does not exist or not online."
|
|||
|
end
|
|||
|
local level = tonumber(value)
|
|||
|
if not level then
|
|||
|
return true, "Error: Value of the level missed."
|
|||
|
end
|
|||
|
player:get_meta():set_int("ptol:level", level)
|
|||
|
minetest.chat_send_player(name, "The level for "..player_name.." ".."set to".." "..value)
|
|||
|
end,
|
|||
|
})
|