ptol/init.lua

219 lines
6.6 KiB
Lua
Raw Normal View History

2021-07-30 16:46:16 -07:00
--
-- 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")
2021-07-31 15:48:19 -07:00
ptol.settings.shape = settings:get("shape") or "box"
2021-07-30 16:46:16 -07:00
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 (xcx)2+(ycy)2+(zcz)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
2021-07-31 15:48:19 -07:00
local function player_inside_box(player_pos, ptol_level)
player_pos.y = player_pos.y - 1
local radius = ptol.settings.radius * ptol_level
local p1 = {
x = ptol.settings.world_center.x - radius,
y = ptol.settings.world_center.y - radius,
z = ptol.settings.world_center.z - radius,
}
local p2 = {
x = ptol.settings.world_center.x + radius,
y = ptol.settings.world_center.y + radius,
z = ptol.settings.world_center.z + radius,
}
if (p1.x <= player_pos.x) and (player_pos.x <= p2.x)
and (p1.y <= player_pos.y) and (player_pos.y <= p2.y)
and (p1.z <= player_pos.z) and (player_pos.z <= p2.z) then
return true
else
return false
end
end
2021-07-30 16:46:16 -07:00
--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,
2021-08-01 07:47:39 -07:00
on_activate = function(self, staticdata, dtime_s) --on_activate, required
if dtime_s > 0 then --loaded, nor new
self.object:remove()
end
end,
2021-07-30 16:46:16 -07:00
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 })
2021-08-01 08:21:51 -07:00
ptol.players[self.pname] = self.object
2021-07-30 16:46:16 -07:00
end,
})
function ptol.freeze(player)
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)
2021-08-01 07:15:32 -07:00
ptol.show_warning(player)
minetest.sound_play("ptol_warning", {to_player = player:get_player_name(), gain = 1.0, max_hear_distance = 10,})
2021-07-30 16:46:16 -07:00
end
function ptol.unfreeze(player)
2021-08-01 08:21:51 -07:00
local player_name = player:get_player_name()
2021-08-01 08:24:22 -07:00
ptol.players[player_name]:remove() --remove the entity
ptol.players[player_name] = nil --remove the player registry
2021-08-01 07:15:32 -07:00
ptol.remove_warning(player)
2021-07-30 16:46:16 -07:00
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
2021-08-01 08:03:26 -07:00
minetest.register_on_leaveplayer(function(player)
2021-08-01 07:15:32 -07:00
if ptol.is_frozen(player) then
ptol.unfreeze(player)
end
end)
2021-07-30 16:46:16 -07:00
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer <= ptol.settings.time then
return
else
timer = 0
2021-07-30 16:46:16 -07:00
end
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))
2021-07-31 15:48:19 -07:00
local player_inside
if ptol.settings.shape == "sphere" then
player_inside = player_inside_sphere(player_pos, ptol_level)
else
player_inside = player_inside_box(player_pos, ptol_level)
end
2021-08-01 07:15:32 -07:00
local frozen = ptol.is_frozen(player)
2021-07-31 15:48:19 -07:00
if not player_inside then
2021-07-30 16:46:16 -07:00
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))
--minetest.chat_send_all(tostring(angle_to_center)..":"..tostring(ptol.settings.allowed_angle))
local controls = player:get_player_control()
local not_allowed_control = false
if controls["down"] or controls["right"] or controls["left"] then
not_allowed_control = true
end
if not(frozen) and ((angle_to_center > ptol.settings.allowed_angle) or not_allowed_control) then
2021-07-30 16:46:16 -07:00
ptol.freeze(player)
--minetest.chat_send_all("freeze")
elseif frozen and (angle_to_center <= ptol.settings.allowed_angle) and not(not_allowed_control) then
2021-07-30 16:46:16 -07:00
ptol.unfreeze(player)
--minetest.chat_send_all("unfreeze")
end
2021-08-01 07:15:32 -07:00
else
if frozen then
ptol.unfreeze(player)
end
2021-07-30 16:46:16 -07:00
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,
})