Added a raw portals mechanism, bugfixes and added texture for the anti-expropriation field
parent
8a42bc5f70
commit
7f82e2adf1
|
@ -0,0 +1,17 @@
|
|||
-- GUN CONFIGURATION --
|
||||
|
||||
gsettings = {}
|
||||
-- gravity acceleration (metres/second^2)
|
||||
gsettings.SPLASH_STREAM_GRAVITY = 9.8
|
||||
|
||||
-- speed of stream splash (metres/second)
|
||||
gsettings.SPLASH_STREAM_SPEED = 50
|
||||
|
||||
-- lifetime of splash drop (seconds)
|
||||
gsettings.SPLASH_DROP_LIFETIME = 2
|
||||
|
||||
-- splash stream collision box
|
||||
gsettings.SPLASH_STREAM_COLLISION_BOX = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1}
|
||||
|
||||
-- splash drop collision box
|
||||
gsettings.SPLASH_DROP_COLLISION_BOX = {-0.05, -0.05, -0.05, 0.05, 0.05, 0.05}
|
|
@ -1 +1 @@
|
|||
|
||||
default
|
||||
|
|
280
gun.lua
280
gun.lua
|
@ -1,17 +1,34 @@
|
|||
local gun = {}
|
||||
-- PORTAL GUN --
|
||||
|
||||
gun.SPLASH_STREAM_GRAVITY = 9.8
|
||||
gun.SPLASH_STREAM_SPEED = 50 -- metres/second
|
||||
gun.SPLASH_DROP_LIFETIME = 2 -- seconds
|
||||
gun = {}
|
||||
|
||||
gun.generate_splash_bounces = function(pos, normal, splash_color)
|
||||
gun.generate_splash_particles = function(pos, normal, splash_color)
|
||||
local rand_amount = math.random(20, 25)
|
||||
|
||||
local side = vector.rotate_around_axis({x=normal.x, y=0, z=normal.z}, {x=0, y=1, z=0}, math.pi/2)
|
||||
|
||||
local signs = {-1, 1}
|
||||
for i = 1, rand_amount do
|
||||
local rand_pitch = math.rad(math.random(10, 45)) * signs[math.random(1, 2)]
|
||||
|
||||
local min_vel_dir = vector.rotate(normal, {x=0, y=-math.pi/4, z=0})
|
||||
local max_vel_dir = vector.rotate(normal, {x=-math.pi/4, y=math.pi/4, z=0})
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = rand_amount,
|
||||
time = 0.1,
|
||||
minpos = pos,
|
||||
maxpos = pos,
|
||||
minvel = vector.multiply(min_vel_dir, 5),
|
||||
maxvel = vector.multiply(max_vel_dir, 5),
|
||||
minacc = {x=0, y=-gsettings.SPLASH_STREAM_GRAVITY, z=0},
|
||||
maxacc = {x=0, y=-gsettings.SPLASH_STREAM_GRAVITY, z=0},
|
||||
minexptime = 1.5,
|
||||
maxexptime = 2.5,
|
||||
minsize = 3,
|
||||
maxsize = 3.5,
|
||||
collisiondetection = false,
|
||||
collision_removal = false,
|
||||
object_collision = false,
|
||||
texture = "portaltest_splash_drop.png^[multiply:" .. splash_color,
|
||||
glow = 7
|
||||
})
|
||||
--[[for i = 1, rand_amount do
|
||||
local rand_pitch = -math.rad(math.random(10, 45))
|
||||
local rand_yaw = math.rad(math.random(10, 45)) * signs[math.random(1, 2)]
|
||||
|
||||
normal = vector.rotate_around_axis(normal, side, rand_pitch)
|
||||
|
@ -21,8 +38,8 @@ gun.generate_splash_bounces = function(pos, normal, splash_color)
|
|||
|
||||
local splash_drop = minetest.add_entity(pos, "portaltest:splash_drop")
|
||||
splash_drop:set_properties({textures={"portaltest_splash_drop.png^[multiply:" .. splash_color}})
|
||||
splash_drop:set_velocity(vector.multiply(res_dir, 10))
|
||||
end
|
||||
splash_drop:set_velocity(vector.multiply(res_dir, 4))
|
||||
end]]
|
||||
end
|
||||
|
||||
gun.bounce_splash_drop = function(drop, surface_normal)
|
||||
|
@ -31,7 +48,7 @@ gun.bounce_splash_drop = function(drop, surface_normal)
|
|||
if not self then return end
|
||||
|
||||
local new_vel = vector.multiply(self.last_velocity, -1)
|
||||
local cross = vector.cross(new_vel, surface_normal)
|
||||
local cross = vector.cross(surface_normal, new_vel)
|
||||
new_vel = vector.rotate_around_axis(new_vel, cross, vector.angle(surface_normal, new_vel)*2)
|
||||
|
||||
drop:set_velocity(new_vel)
|
||||
|
@ -40,7 +57,7 @@ end
|
|||
gun.global_step_through_players_with_guns = function()
|
||||
local players = minetest.get_connected_players()
|
||||
|
||||
for i, player in ipairs(players) do
|
||||
for _, player in ipairs(players) do
|
||||
if player:get_wielded_item():get_name() == "portaltest:gun_empty" then
|
||||
local ctrls = player:get_player_control()
|
||||
local color = ""
|
||||
|
@ -55,13 +72,19 @@ gun.global_step_through_players_with_guns = function()
|
|||
|
||||
player:set_wielded_item(ItemStack("portaltest:gun_" .. color))
|
||||
local pl_pos = player:get_pos()
|
||||
local rel_offset_pos = vector.add(vector.new(0, 0, 1), vector.new(1, 0, 0))
|
||||
local rel_offset_pos = vector.new(0.5, 0, 0)
|
||||
rel_offset_pos.y = 0.5
|
||||
|
||||
rel_offset_pos = vector.rotate(rel_offset_pos, {x=player:get_look_vertical(), y=player:get_look_horizontal(), z=0})
|
||||
local dir = player:get_look_dir()
|
||||
local dir_rot = vector.dir_to_rotation(dir)
|
||||
rel_offset_pos = vector.rotate(rel_offset_pos, dir_rot)
|
||||
local pos = vector.add(pl_pos, rel_offset_pos)
|
||||
local splash_stream = minetest.add_entity(pos, "portaltest:splash_stream")
|
||||
splash_stream:set_properties({textures={"portaltest_splash_stream.png^[multiply:" .. color}})
|
||||
splash_stream:set_velocity(vector.multiply(player:get_look_dir(), gun.SPLASH_STREAM_SPEED))
|
||||
splash_stream:set_velocity(vector.multiply(dir, gsettings.SPLASH_STREAM_SPEED))
|
||||
|
||||
local self = splash_stream:get_luaentity()
|
||||
self.stream_emitter = player:get_player_name()
|
||||
|
||||
minetest.after(0.5, function()
|
||||
player:set_wielded_item(ItemStack("portaltest:gun_empty"))
|
||||
|
@ -70,6 +93,100 @@ gun.global_step_through_players_with_guns = function()
|
|||
end
|
||||
end
|
||||
|
||||
gun.get_pointedthing_info = function(pos, dir, ray_length)
|
||||
local pos2 = vector.add(pos, vector.multiply(dir, ray_length))
|
||||
local raycast = minetest.raycast(pos, pos2)
|
||||
|
||||
local target_pt
|
||||
for pt in raycast do
|
||||
if pt.type == "object" then
|
||||
local self = pt.ref:get_luaentity()
|
||||
if self then
|
||||
minetest.debug("ray has intersected an object with name: " .. self.name)
|
||||
if self.name ~= "portaltest:splash_stream" then
|
||||
target_pt = pt
|
||||
break
|
||||
else
|
||||
--minetest.debug("raycast: " .. self.name)
|
||||
end
|
||||
end
|
||||
elseif pt.type == "node" then
|
||||
minetest.debug("raycast has intersected a node with name: " .. minetest.get_node(pt.under).name)
|
||||
target_pt = pt
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return target_pt
|
||||
end
|
||||
|
||||
gun.update_player_portals_datas = function(player_meta)
|
||||
local player_portals = minetest.deserialize(player_meta:get_string("portals"))
|
||||
|
||||
if not player_portals or player_portals == {} then
|
||||
return
|
||||
end
|
||||
|
||||
local new_datas = {}
|
||||
|
||||
for color, pos in pairs(player_portals) do
|
||||
local actual_node = minetest.get_node(player_portals[color])
|
||||
|
||||
if actual_node.name == "portaltest:portal_" .. color then
|
||||
new_datas[color] = {x=pos.x, y=pos.y, z=pos.z}
|
||||
end
|
||||
end
|
||||
|
||||
player_meta:set_string("portals", minetest.serialize(new_datas))
|
||||
end
|
||||
|
||||
gun.place_portal = function(placer, pt, color, param2, dir_to_top)
|
||||
local meta = placer:get_meta()
|
||||
gun.update_player_portals_datas(meta)
|
||||
local player_portals = minetest.deserialize(meta:get_string("portals"))
|
||||
|
||||
if not player_portals or player_portals == {} then
|
||||
player_portals = {}
|
||||
end
|
||||
|
||||
if portal.is_pos_busy_by_portal(pt.above) then
|
||||
return
|
||||
end
|
||||
|
||||
if player_portals[color] then
|
||||
minetest.remove_node(player_portals[color])
|
||||
end
|
||||
|
||||
player_portals[color] = pt.above
|
||||
|
||||
meta:set_string("portals", minetest.serialize(player_portals))
|
||||
|
||||
minetest.add_node(pt.above, {name = "portaltest:portal_" .. color, param2 = param2})
|
||||
|
||||
local setp_meta = minetest.get_meta(player_portals[color])
|
||||
|
||||
local cp_pos
|
||||
|
||||
if color == "orange" then
|
||||
if player_portals["blue"] then
|
||||
cp_pos = player_portals["blue"]
|
||||
end
|
||||
elseif color == "blue" then
|
||||
if player_portals["orange"] then
|
||||
cp_pos = player_portals["orange"]
|
||||
end
|
||||
end
|
||||
|
||||
if cp_pos then
|
||||
setp_meta:set_string("connected_to", minetest.serialize(cp_pos))
|
||||
|
||||
local cp_meta = minetest.get_meta(cp_pos)
|
||||
cp_meta:set_string("connected_to", minetest.serialize(player_portals[color]))
|
||||
end
|
||||
|
||||
setp_meta:set_string("dir_to_top", minetest.serialize(dir_to_top))
|
||||
end
|
||||
|
||||
minetest.register_node("portaltest:gun_empty", {
|
||||
drawtype = "mesh",
|
||||
visual_scale = 0.5,
|
||||
|
@ -141,17 +258,108 @@ minetest.register_entity("portaltest:splash_stream", {
|
|||
visual_size = {x=1, y=1, z=1},
|
||||
physical = true,
|
||||
collide_with_objects = true,
|
||||
collisionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2},
|
||||
collisionbox = gsettings.SPLASH_STREAM_COLLISION_BOX,
|
||||
selectionbox = {0, 0, 0, 0, 0, 0},
|
||||
textures = {"portaltest_splash_stream.png"},
|
||||
backface_culling = false,
|
||||
glow = 7,
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
self.object:set_acceleration({x=0, y=-gun.SPLASH_STREAM_GRAVITY, z=0})
|
||||
self.move_dir = vector.normalize(self.object:get_velocity())
|
||||
end,
|
||||
on_step = function(self, dtime, moveresult)
|
||||
if moveresult.collides then
|
||||
local colls = moveresult.collisions
|
||||
if not moveresult.collides then
|
||||
self.move_dir = vector.normalize(self.object:get_velocity())
|
||||
else
|
||||
local pos = self.object:get_pos()
|
||||
local vel = self.object:get_velocity()
|
||||
minetest.debug("cur_vel: " .. vector.length(vel))
|
||||
local texture = self.object:get_properties().textures[1]
|
||||
|
||||
self.object:remove()
|
||||
--minetest.debug("self.last_velocity: " .. minetest.pos_to_string(self.last_velocity))
|
||||
--minetest.debug("current velocity: " .. minetest.pos_to_string(vel))
|
||||
|
||||
local pt
|
||||
if vector.length(self.move_dir) == 0 then
|
||||
pt = gun.get_pointedthing_info(pos, vector.normalize(vel), 1)
|
||||
else
|
||||
pt = gun.get_pointedthing_info(pos, self.move_dir, 1)
|
||||
end
|
||||
|
||||
if pt then
|
||||
minetest.debug("\'pt\' is not nil!")
|
||||
--minetest.debug("pt.type: " .. pt.type)
|
||||
--minetest.debug("pt.intersection_normal: " .. minetest.pos_to_string(pt.intersection_normal))
|
||||
--minetest.debug("pt.type: " .. pt.type)
|
||||
local s, e = texture:find("%^%[multiply:", 1)
|
||||
local color = texture:sub(e+1, texture:len())
|
||||
local player = minetest.get_player_by_name(self.stream_emitter)
|
||||
if pt.type == "node" then
|
||||
if pt.intersection_normal.y == 0 then
|
||||
-- Portal is placed on the wall
|
||||
local node = minetest.get_node_or_nil(pt.under)
|
||||
local node2 = minetest.get_node_or_nil(vector.new(pt.under.x, pt.under.y+1, pt.under.z))
|
||||
|
||||
if (node and node.name == "portaltest:panel_mono") and
|
||||
(node2 and node2.name == "portaltest:panel_mono") and
|
||||
minetest.get_node({x=pt.above.x, y=pt.above.y+1, z=pt.above.z}).name == "air" then
|
||||
|
||||
gun.place_portal(player, pt, color, minetest.dir_to_facedir(pt.intersection_normal), {x=0, y=1, z=0})
|
||||
end
|
||||
else
|
||||
-- Portal is placed on the floor/ceiling
|
||||
local look_dir = player:get_look_dir()
|
||||
local horiz_look_dir = vector.new(look_dir.x, 0, look_dir.z)
|
||||
local x_horiz_dir = vector.new(look_dir.x, 0, 0)
|
||||
local z_horiz_dir = vector.new(0, 0, look_dir.z)
|
||||
local target_horiz_dir = vector.angle(x_horiz_dir, horiz_look_dir) < vector.angle(horiz_look_dir, z_horiz_dir) and x_horiz_dir or z_horiz_dir
|
||||
|
||||
local node = minetest.get_node_or_nil(pt.under)
|
||||
local node2 = minetest.get_node_or_nil(vector.add(pt.under, target_horiz_dir))
|
||||
local node3 = minetest.get_node_or_nil(vector.add(pt.under, vector.add(pt.intersection_normal, target_horiz_dir)))
|
||||
|
||||
if (node and node.name == "portaltest:panel_mono") and
|
||||
(node2 and node2.name == "portaltest:panel_mono") and
|
||||
(node3 and node3.name == "air") then
|
||||
|
||||
-- Keys are param2 values, values are corresponding directions
|
||||
local y_up_rots = {
|
||||
[6] = {x=0, y=0, z=1},
|
||||
[8] = {x=0, y=0, z=-1},
|
||||
[15] = {x=1, y=0, z=0},
|
||||
[17] = {x=-1, y=0, z=0}
|
||||
}
|
||||
|
||||
local y_down_rots = {
|
||||
[4] = {x=0, y=0, z=-1},
|
||||
[10] = {x=0, y=0, z=1},
|
||||
[13] = {x=-1, y=0, z=0},
|
||||
[19] = {x=1, y=0, z=0}
|
||||
}
|
||||
|
||||
local target_param2
|
||||
local dir_to_top
|
||||
|
||||
local nrmlzed_thd = vector.normalize(target_horiz_dir)
|
||||
local target_y_rots = pt.intersection_normal.y == 1 and y_up_rots or y_down_rots
|
||||
|
||||
for p2, dir in pairs(target_y_rots) do
|
||||
if vector.equals(nrmlzed_thd, dir) then
|
||||
target_param2 = p2
|
||||
dir_to_top = dir
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
gun.place_portal(player, pt, color, target_param2, dir_to_top)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
gun.generate_splash_particles(pt.intersection_point, pt.intersection_normal, color)
|
||||
|
||||
end
|
||||
--[[local colls = moveresult.collisions
|
||||
minetest.debug("moveresult.collisions: " .. #moveresult.collisions)
|
||||
|
||||
local sum_normal = vector.new()
|
||||
|
@ -171,23 +379,23 @@ minetest.register_entity("portaltest:splash_stream", {
|
|||
local s, e = texture:find("%^%[multiply:", 1)
|
||||
gun.generate_splash_bounces(pos, sum_normal, texture:sub(e+1, texture:len()))
|
||||
|
||||
self.object:remove()
|
||||
self.object:remove()]]
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_entity("portaltest:splash_drop", {
|
||||
--[[minetest.register_entity("portaltest:splash_drop", {
|
||||
visual = "sprite",
|
||||
visual_size = {x=1, y=1, z=1},
|
||||
physical = true,
|
||||
collide_with_objects = true,
|
||||
textures = {"portaltest_splash_drop.png"},
|
||||
collisionbox = {-0.05, -0.05, -0.05, 0.05, 0.05, 0.05},
|
||||
collisionbox = gsettings.SPLASH_DROP_COLLISION_BOX,
|
||||
selectionbox = {0, 0, 0, 0, 0, 0},
|
||||
backface_culling = false,
|
||||
glow = 7,
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
self.object:set_acceleration({x=0, y=-gun.SPLASH_STREAM_GRAVITY, z=0})
|
||||
self.object:set_acceleration({x=0, y=-gsettings.SPLASH_STREAM_GRAVITY, z=0})
|
||||
self.last_velocity = self.object:get_velocity()
|
||||
self.dtime = 0
|
||||
end,
|
||||
|
@ -197,22 +405,24 @@ minetest.register_entity("portaltest:splash_drop", {
|
|||
if not moveresult.collides then
|
||||
self.last_velocity = self.object:get_velocity()
|
||||
else
|
||||
local pos = self.object:get_pos()
|
||||
local vel = self.object:get_velocity()
|
||||
local pos2 = vector.add(pos, vector.multiply(vel, dtime))
|
||||
local raycast = minetest.raycast(pos, pos2)
|
||||
local pt = raycast:next()
|
||||
|
||||
if pt then
|
||||
local min_cb_pos = {
|
||||
x = gsettings.SPLASH_DROP_COLLISION_BOX[1],
|
||||
y = gsettings.SPLASH_DROP_COLLISION_BOX[2],
|
||||
z = gsettings.SPLASH_DROP_COLLISION_BOX[3]
|
||||
}
|
||||
|
||||
local pt = gun.get_pointedthing_info(self.object:get_pos(), self.last_velocity, 1, dtime)
|
||||
|
||||
if pt and pt.intersection_normal then
|
||||
gun.bounce_splash_drop(self.object, pt.intersection_normal)
|
||||
end
|
||||
end
|
||||
|
||||
if self.dtime >= gun.SPLASH_DROP_LIFETIME then
|
||||
if self.dtime >= gsettings.SPLASH_DROP_LIFETIME then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})
|
||||
})]]
|
||||
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
|
3
init.lua
3
init.lua
|
@ -1,3 +1,6 @@
|
|||
local modpath = minetest.get_modpath("portaltest")
|
||||
|
||||
dofile(modpath .. "/config.lua")
|
||||
dofile(modpath .. "/gun.lua")
|
||||
dofile(modpath .. "/panels.lua")
|
||||
dofile(modpath .. "/portal.lua")
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
panels.lua
10
panels.lua
|
@ -1,10 +1,8 @@
|
|||
-- WHITE PANELS FROM MOON ROCK --
|
||||
|
||||
minetest.register_node("portaltest:panel_mono", {
|
||||
description = "Mono Panel",
|
||||
drawtype = "normal",
|
||||
tiles = {"portaltest_while_panel.png"},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
groups = {cracky=1.5},
|
||||
tiles = {"portaltest_white_panel.png"},
|
||||
groups = {cracky=1.5, moonpanel = 1},
|
||||
sounds = default.node_sound_stone_defaults()
|
||||
})
|
||||
|
|
240
portal.lua
240
portal.lua
|
@ -1 +1,239 @@
|
|||
|
||||
-- PORTALS --
|
||||
|
||||
portal = {}
|
||||
|
||||
-- Return unit direction of node with position 'pos'.
|
||||
portal.dir = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local back_dir = minetest.facedir_to_dir(node.param2)
|
||||
|
||||
local dir = vector.multiply(back_dir, -1)
|
||||
|
||||
return dir
|
||||
end
|
||||
|
||||
-- Rotates obj`s collision and selection boxes angles 'rot' (in radians).
|
||||
-- Rotation occurs relatively to obj`s box rotation!!!
|
||||
portal.rotate_entity_bounding_box = function(obj, rot)
|
||||
if not obj:get_luaentity() then return end
|
||||
|
||||
if not (math.deg(rot.x) % 90 == 0) or not (math.deg(rot.y) % 90 == 0) or not (math.deg(rot.z) % 90 == 0) then return end
|
||||
|
||||
local def = obj:get_properties()
|
||||
local colbox = def.collisionbox
|
||||
local selbox = def.selectionbox
|
||||
local new_colbox = {}
|
||||
local new_selbox = {}
|
||||
|
||||
new_colbox[1] = vector.rotate({x=colbox[1], y=colbox[2], z=colbox[3]}, rot)
|
||||
new_colbox[2] = vector.rotate({x=colbox[4], y=colbox[5], z=colbox[6]}, rot)
|
||||
|
||||
new_selbox[1] = vector.rotate({x=selbox[1], y=selbox[2], z=selbox[3]}, rot)
|
||||
new_selbox[2] = vector.rotate({x=selbox[4], y=selbox[5], z=selbox[6]}, rot)
|
||||
|
||||
local res_colbox = {
|
||||
new_colbox[1].x, new_colbox[1].y, new_colbox[1].z,
|
||||
new_colbox[2].x, new_colbox[2].y, new_colbox[2].z
|
||||
}
|
||||
|
||||
local res_selbox = {
|
||||
new_selbox[1].x, new_selbox[1].y, new_selbox[1].z,
|
||||
new_selbox[2].x, new_selbox[2].y, new_selbox[2].z
|
||||
}
|
||||
|
||||
return res_colbox, res_selbox
|
||||
end
|
||||
|
||||
-- Called each the node timer step.
|
||||
--If there are objects within 'catch_box' box and their collision boxes are located at 0.1 distance to the portal surface, then teleport them saving their impulse.
|
||||
portal.teleport_entity = function(pos)
|
||||
local connected_to = minetest.deserialize(minetest.get_meta(pos):get_string("connected_to"))
|
||||
--minetest.debug("connected_to: " .. (connected_to and minetest.pos_to_string(connected_to) or tostring(nil)))
|
||||
|
||||
if not connected_to then
|
||||
--minetest.debug("Nothing can be teleported at the moment as the portal at " .. minetest.pos_to_string(pos) .. " is unconnected!")
|
||||
return
|
||||
end
|
||||
|
||||
local pdir = minetest.facedir_to_dir(minetest.get_node(pos).param2)
|
||||
-- Catch_box coordinates are relative to the node`s origin (pos)
|
||||
local catch_box = {vector.new(-0.4, -0.4, -0.5), vector.new(0.4, 1.4, -0.5)}
|
||||
local pdir_rot = vector.dir_to_rotation(pdir)
|
||||
|
||||
catch_box[1] = vector.rotate(catch_box[1], pdir_rot)
|
||||
catch_box[2] = vector.add(vector.rotate(catch_box[2], pdir_rot), vector.multiply(pdir, 1.45))
|
||||
minetest.debug("catch_box: [1]=" .. minetest.pos_to_string(vector.add(pos, catch_box[1])) .. ", [2]=" .. minetest.pos_to_string(vector.add(pos, catch_box[2])))
|
||||
|
||||
local catched_objs = minetest.get_objects_in_area(vector.add(pos, catch_box[1]), vector.add(pos, catch_box[2]))
|
||||
--minetest.debug("#catched_objs: " .. #catched_objs)
|
||||
|
||||
local iter_func = function(obj)
|
||||
local centre_point = vector.add(pos, vector.divide(vector.add(catch_box[1], vector.rotate(vector.new(0.4, 1.4, -0.5), pdir_rot)), 2))
|
||||
--minetest.debug("centre_point: " .. minetest.pos_to_string(centre_point))
|
||||
local epos_dir = vector.subtract(obj:get_pos(), centre_point)
|
||||
|
||||
--[[local origin_epos_dir = vector.rotate(epos_dir, vector.multiply(vector.dir_to_rotation(epos_dir), -1))
|
||||
local epos_horiz_dir = vector.rotate(vector.new(origin_epos_dir.x, 0, origin_epos_dir.z), vector.dir_to_rotation(epos_dir))
|
||||
local abs_epos_horiz_dir = vector.add(centre_point, epos_horiz_dir)]]
|
||||
|
||||
local dist_to_epos = vector.length(epos_dir)*math.cos(vector.angle(epos_dir, pdir))
|
||||
--minetest.debug("dist_to_epos: " .. dist_to_epos)
|
||||
local rel_epos_horiz_dir = vector.subtract(epos_dir, vector.multiply(pdir, dist_to_epos))
|
||||
local abs_epos_horiz_dir = vector.add(centre_point, vector.multiply(rel_epos_horiz_dir, -1))
|
||||
|
||||
local raycast = minetest.raycast(abs_epos_horiz_dir, obj:get_pos())
|
||||
|
||||
for pt in raycast do
|
||||
if pt.type == "object" and pt.ref == obj then
|
||||
local dist_to_psurface = vector.distance(abs_epos_horiz_dir, pt.intersection_point)
|
||||
minetest.debug("dist_to_psurface: " .. dist_to_psurface)
|
||||
|
||||
if not (dist_to_psurface < 0.15) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local cportal_dir = minetest.facedir_to_dir(minetest.get_node(connected_to).param2)
|
||||
minetest.debug("cportal_dir: " .. minetest.pos_to_string(cportal_dir))
|
||||
local box_rot = vector.subtract(vector.dir_to_rotation(cportal_dir), vector.dir_to_rotation(pdir_rot))
|
||||
|
||||
local new_colbox, new_selbox = portal.rotate_entity_bounding_box(obj, box_rot)
|
||||
local target_pos = vector.add(connected_to, vector.multiply(vector.divide(cportal_dir, 2), dist_to_epos))
|
||||
minetest.debug("target_pos: " .. minetest.pos_to_string(target_pos))
|
||||
|
||||
if minetest.get_node(target_pos).name ~= "air" and not portal.is_pos_busy_by_portal(target_pos) then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.debug("set_pos()...")
|
||||
obj:set_pos(target_pos)
|
||||
obj:set_properties({collisionbox = new_colbox, selectionbox = new_selbox})
|
||||
|
||||
if obj:is_player() then
|
||||
obj:set_look_vertical(obj:get_look_vertical()+box_rot.x)
|
||||
obj:set_look_horizontal(obj:get_look_horizontal()+box_rot.y)
|
||||
else
|
||||
obj:set_rotation(vector.add(obj:get_rotation(), box_rot))
|
||||
end
|
||||
|
||||
local cur_vel = obj:get_velocity()
|
||||
local target_vel = vector.rotate(cur_vel, box_rot)
|
||||
|
||||
obj:add_velocity(vector.subtract(target_vel, cur_vel))
|
||||
end
|
||||
|
||||
for _, obj in ipairs(catched_objs) do
|
||||
iter_func(obj)
|
||||
end
|
||||
end
|
||||
|
||||
portal.is_pos_busy_by_portal = function(pos)
|
||||
local portal_pos = minetest.find_node_near(pos, 1, {"portaltest:portal_orange", "portaltest:portal_blue"}, true)
|
||||
|
||||
if not portal_pos then return end
|
||||
|
||||
local dir_to_top = minetest.deserialize(minetest.get_meta(portal_pos):get_string("dir_to_top"))
|
||||
local portal_pos2 = vector.add(portal_pos, dir_to_top)
|
||||
|
||||
return vector.distance(pos, portal_pos) < 0.5 or
|
||||
vector.distance(pos, portal_pos2) < 0.5
|
||||
end
|
||||
|
||||
portal.check_for_portal_footing = function(pos)
|
||||
local dir_to_top = minetest.deserialize(minetest.get_meta(pos):get_string("dir_to_top"))
|
||||
local back_dir = vector.multiply(minetest.facedir_to_dir(minetest.get_node(pos).param2), -1)
|
||||
|
||||
local node1 = minetest.get_node(vector.add(pos, back_dir))
|
||||
local node2 = minetest.get_node(vector.add(pos, vector.add(back_dir, dir_to_top)))
|
||||
|
||||
if node1.name == "air" or node2.name == "air" then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
portal.remove = function(pos)
|
||||
local connected_to = minetest.deserialize(minetest.get_meta(pos):get_string("connected_to"))
|
||||
|
||||
if not connected_to or connected_to == {} then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.get_meta(connected_to):set_string("connected_to", "")
|
||||
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
|
||||
minetest.register_node("portaltest:portal_orange", {
|
||||
description = "Portal",
|
||||
drawtype = "mesh",
|
||||
mesh = "portaltest_portal.b3d",
|
||||
tiles = {"portaltest_orange_portal.png"},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
light_source = 14,
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.4, -0.4}, -- Bottom Box
|
||||
{-0.5, -0.4, -0.5, -0.4, 1.4, -0.4}, -- Left Box
|
||||
{0.4, -0.4, -0.5, 0.5, 1.4, -0.4}, -- Right Box
|
||||
{-0.5, 1.4, -0.5, 0.5, 1.5, -0.4} -- Top Box
|
||||
}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0, 0, 0, 0, 0, 0}
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(0.1)
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
portal.remove(pos)
|
||||
end,
|
||||
on_timer = function(pos, elapsed)
|
||||
portal.teleport_entity(pos)
|
||||
portal.check_for_portal_footing(pos)
|
||||
return true
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node("portaltest:portal_blue", {
|
||||
description = "Portal",
|
||||
drawtype = "mesh",
|
||||
mesh = "portaltest_portal.b3d",
|
||||
tiles = {"portaltest_blue_portal.png"},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
light_source = 14,
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.4, -0.4}, -- Bottom Box
|
||||
{-0.5, -0.4, -0.5, -0.4, 1.4, -0.4}, -- Left Box
|
||||
{0.4, -0.4, -0.5, 0.5, 1.4, -0.4}, -- Right Box
|
||||
{-0.5, 1.4, -0.5, 0.5, 1.5, -0.4} -- Top Box
|
||||
}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0, 0, 0, 0, 0, 0}
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(0.1)
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
portal.remove(pos)
|
||||
end,
|
||||
on_timer = function(pos, elapsed)
|
||||
portal.teleport_entity(pos)
|
||||
portal.check_for_portal_footing(pos)
|
||||
return true
|
||||
end
|
||||
})
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.9 KiB |
Loading…
Reference in New Issue