Added aerial faith plates model/texture, the portal gun is entity now, added animation and visual effects of shooting

master
Andrey2470T 2021-10-03 02:00:18 +03:00
parent 7f82e2adf1
commit b45891677c
19 changed files with 294 additions and 94 deletions

41
aerial_faith_plate.lua Normal file
View File

@ -0,0 +1,41 @@
minetest.register_node("portaltest:aerial_faith_plate", {
description = "Aerial Faith Plate (Click to set up parameters of bouncing)",
drawtype = "nodebox",
tiles = {
"portaltest_aerial_faith_plate_top.png",
"portaltest_aerial_faith_plate_bottom.png",
"portaltest_aerial_faith_plate_side.png"
},
use_texture_alpha = true,
paramtype = "light",
paramtype2 = "facedir",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.41, 0.5}
},
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.41, 0.5}
},
groups = {choppy=2.5},
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", [[
formspec_version[4]
size[9,7]
style_type[label;font=normal,bold;font_size=*1.5]
]] ..
"label[1.5,1;Set up bouncing direction and\n maximum height and distance:]" ..
[[
style_type[label;font=normal,bold;font_size=]
label[1.5,2.5;Max Height:]
label[5.5,2.5;Max Distance:]
label[3.5,4;Direction:]
field[1.5,3;2,0.5;max_height;;]
field[5.5,3;2,0.5;max_distance;;]
field[3.5,4.5;2,0.5;direction;;]
button[3,5.5;3,1;save;Save]
]])
end
})

View File

@ -11,7 +11,7 @@ gsettings.SPLASH_STREAM_SPEED = 50
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}
gsettings.SPLASH_STREAM_COLLISION_BOX = {-0.01, -0.01, -0.01, 0.01, 0.01, 0.01}
-- splash drop collision box
gsettings.SPLASH_DROP_COLLISION_BOX = {-0.05, -0.05, -0.05, 0.05, 0.05, 0.05}
gsettings.SPLASH_DROP_COLLISION_BOX = {-0.005, -0.005, -0.005, 0.005, 0.005, 0.005}

342
gun.lua
View File

@ -2,12 +2,17 @@
gun = {}
-- Table for referencing to a gun entity of each player that is wielding that currently
gun.spawned_guns = {}
local gun_shift = {x=0.3, y=1.2, z=0.5}
gun.generate_splash_particles = function(pos, normal, splash_color)
local rand_amount = math.random(20, 25)
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})
local min_vel_dir = vector.rotate(normal, {x=-math.pi/4, 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,
@ -27,41 +32,152 @@ gun.generate_splash_particles = function(pos, normal, splash_color)
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)
local up = vector.cross(side, normal)
local res_dir = vector.rotate_around_axis(normal, up, rand_yaw)
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, 4))
end]]
end
-- Recalculates a new position and rotation for gun relatively to the player`s rotation.
gun.calculate_gun_pos_and_rot = function(player)
local rot = {x=-player:get_look_vertical(), y=player:get_look_horizontal(), z=0}
local pos = vector.add(player:get_pos(), vector.rotate(gun_shift, {x=0, y=player:get_look_horizontal(), z=0}))
return pos, rot
end
-- Shifts the gun entity backward and turns right a bit for a visual effect while shooting. Also knockback a bit the player`s camera.
gun.knockback_gun = function(player, gun)
local shift_back = -0.05
local rot_right = -math.rad(1)
local cam_rot_d = -math.rad(5)
local elapsed = 0.0
local dtime = 0.05
local orig_cam_dir = player:get_look_dir()
minetest.debug("gun.knockback_gun()")
local function knockback(gun)
elapsed = elapsed + dtime
minetest.debug("elapsed: " .. tostring(elapsed))
if not gun:get_luaentity() then
return
end
if elapsed >= 0.5 and elapsed < 0.55 or elapsed > 0.45 and elapsed <= 0.5 then
minetest.debug("elapsed = 0.5")
rot_right = -rot_right
shift_back = -shift_back
cam_rot_d = -cam_rot_d
end
player:set_look_vertical(player:get_look_vertical()+cam_rot_d)
gun:set_pos(vector.add(gun:get_pos(), vector.multiply(orig_cam_dir, shift_back)))
local cur_rot = gun:get_rotation()
gun:set_rotation({x=cur_rot.x, y=cur_rot.y+rot_right, z=cur_rot.z})
if elapsed < 1.0 then
minetest.after(dtime, knockback, gun)
else
player:get_meta():set_string("is_shooting", "")
end
return true
end
minetest.after(dtime, knockback, gun)
return true
end
gun.bounce_splash_drop = function(drop, surface_normal)
local self = drop:get_luaentity()
if not self then return end
local new_vel = vector.multiply(self.last_velocity, -1)
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)
end
gun.shoot = function(player, gun, ball_color)
if not gun:get_luaentity() then
return
end
local dir = player:get_look_dir()
local gun_pos = gun:get_pos()
local gun_ball = minetest.add_entity(gun_pos, "portaltest:gun_ball")
gun_ball:set_properties({textures={"portaltest_gun_ball.png^[multiply:" .. ball_color}})
gun_ball:set_velocity(vector.multiply(dir, gsettings.SPLASH_STREAM_SPEED))
return true
end
gun.global_step_through_players_with_guns = function()
local players = minetest.get_connected_players()
for _, player in ipairs(players) do
if player:get_wielded_item():get_name() == "portaltest:gun_empty" then
local name = player:get_player_name()
if player:get_wielded_item():get_name() == "portaltest:gun_item" then
local gun_pos, gun_rot = gun.calculate_gun_pos_and_rot(player)
if not gun.spawned_guns[name] then
minetest.debug("add gun entity")
gun.spawned_guns[name] = minetest.add_entity(gun_pos, "portaltest:gun")
player_api.set_model(player, "portaltest_player_with_gun.b3d")
else
gun.spawned_guns[name]:set_pos(gun_pos)
end
gun.spawned_guns[name]:set_rotation(gun_rot)
local ctrls = player:get_player_control()
local anim
local speed = 30
local meta = player:get_meta()
if ctrls.up or ctrls.right then
anim = "walk_forward"
elseif ctrls.down or ctrls.left then
anim = "walk_backward"
elseif ctrls.LMB or ctrls.RMB then
if meta:get_string("is_shooting") == "" then
minetest.debug("\'is_shooting\' is empty!")
anim = "shoot"
speed = 10
local gun_color = ctrls.LMB and "blue" or "orange"
meta:set_string("is_shooting", "1")
minetest.debug("\'is_shooting\' is 1!")
gun.spawned_guns[name]:set_properties({textures={"portaltest_gun.png", "portaltest_gun_" .. gun_color .. "_tube.png"}})
gun.shoot(player, gun.spawned_guns[name], gun_color)
gun.knockback_gun(player, gun.spawned_guns[name])
end
elseif meta:get_string("is_shooting") == "" then
anim = "stand"
end
player_api.set_animation(player, anim, speed)
else
if gun.spawned_guns[name] then
gun.spawned_guns[name]:remove()
gun.spawned_guns[name] = nil
player_api.set_model(player, "character.b3d")
end
end
--[[
local ctrls = player:get_player_control()
local color = ""
if ctrls.LMB then
color = "blue"
elseif ctrls.RMB then
@ -69,12 +185,12 @@ gun.global_step_through_players_with_guns = function()
else
return
end
player:set_wielded_item(ItemStack("portaltest:gun_" .. color))
local pl_pos = player:get_pos()
local rel_offset_pos = vector.new(0.5, 0, 0)
rel_offset_pos.y = 0.5
local dir = player:get_look_dir()
local dir_rot = vector.dir_to_rotation(dir)
rel_offset_pos = vector.rotate(rel_offset_pos, dir_rot)
@ -82,24 +198,24 @@ gun.global_step_through_players_with_guns = function()
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(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"))
end)
end
end]]
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
--[[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)
@ -110,33 +226,35 @@ gun.get_pointedthing_info = function(pos, dir, ray_length)
--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
else]]
if pt.type == "node" then
--minetest.debug("raycast has intersected a node with name: " .. minetest.get_node(pt.under).name)
return pt
--target_pt = pt
--break
end
end
return target_pt
return
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
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
@ -144,11 +262,11 @@ 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
@ -156,17 +274,17 @@ gun.place_portal = function(placer, pt, color, param2, dir_to_top)
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"]
@ -176,18 +294,53 @@ gun.place_portal = function(placer, pt, color, param2, dir_to_top)
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", {
-- Player model with gun
player_api.register_model("portaltest_player_with_gun.b3d", {
animations = {
stand = {x = 1, y = 80},
sit = {x = 81, y = 161},
lay = {x = 162, y = 167},
walk_forward = {x = 168, y = 188},
walk_backward = {x = 188, y = 168},
shoot = {x = 189, y = 199}
}
})
-- Portal gun
minetest.register_entity("portaltest:gun", {
visual_size = {x=3, y=3, z=3},
physical = false,
collision_box = {0, 0, 0, 0, 0, 0},
pointable = false,
visual = "mesh",
mesh = "portaltest_gun.b3d",
textures = {"portaltest_gun.png"},
glow = 4,
static_save = false
})
minetest.register_craftitem("portaltest:gun_item", {
description = "Portal Gun",
inventory_image = "portaltest_gun_inv.png",
wield_image = "portaltest_gun_inv.png^[opacity:0",
range = 0.0
})
-- Legacy code
--[[minetest.register_node("portaltest:gun_empty", {
drawtype = "mesh",
visual_scale = 0.5,
tiles = {"portaltest_gun.png^portaltest_gun_empty_tube.png"},
@ -205,9 +358,9 @@ minetest.register_node("portaltest:gun_empty", {
on_place = function(itemstack, placer, pointed_thing)
return nil
end
})
})
minetest.register_node("portaltest:gun_orange", {
drawtype = "mesh",
visual_scale = 0.5,
@ -248,19 +401,19 @@ minetest.register_node("portaltest:gun_blue", {
on_place = function(itemstack, placer, pointed_thing)
return nil
end
})
})]]
minetest.register_entity("portaltest:splash_stream", {
minetest.register_entity("portaltest:gun_ball", {
visual = "sprite",
visual_size = {x=1, y=1, z=1},
physical = true,
collide_with_objects = true,
collide_with_objects = false,
collisionbox = gsettings.SPLASH_STREAM_COLLISION_BOX,
selectionbox = {0, 0, 0, 0, 0, 0},
textures = {"portaltest_splash_stream.png"},
textures = {"portaltest_gun_ball.png"},
backface_culling = false,
glow = 7,
on_activate = function(self, staticdata, dtime_s)
@ -274,18 +427,18 @@ minetest.register_entity("portaltest:splash_stream", {
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
local pt = gun.get_pointedthing_info(pos, self.move_dir, 1)
--[[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
end]]
if pt then
minetest.debug("\'pt\' is not nil!")
--minetest.debug("pt.type: " .. pt.type)
@ -293,17 +446,17 @@ minetest.register_entity("portaltest:splash_stream", {
--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
--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
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
@ -313,15 +466,15 @@ minetest.register_entity("portaltest:splash_stream", {
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},
@ -329,20 +482,20 @@ minetest.register_entity("portaltest:splash_stream", {
[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
@ -350,18 +503,18 @@ minetest.register_entity("portaltest:splash_stream", {
break
end
end
gun.place_portal(player, pt, color, target_param2, dir_to_top)
end
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()
for _, coll in ipairs(colls) do
if coll.axis == "x" then
@ -372,13 +525,13 @@ minetest.register_entity("portaltest:splash_stream", {
sum_normal = vector.add(sum_normal, vector.normalize({x=0, y=0, z=coll.old_velocity.z}))
end
end
sum_normal = vector.multiply(sum_normal, -1)
local pos = self.object:get_pos()
local texture = self.object:get_properties().textures[1]
local s, e = texture:find("%^%[multiply:", 1)
gun.generate_splash_bounces(pos, sum_normal, texture:sub(e+1, texture:len()))
self.object:remove()]]
end
end
@ -401,7 +554,7 @@ minetest.register_entity("portaltest:splash_stream", {
end,
on_step = function(self, dtime, moveresult)
self.dtime = self.dtime + dtime
if not moveresult.collides then
self.last_velocity = self.object:get_velocity()
else
@ -410,20 +563,25 @@ minetest.register_entity("portaltest:splash_stream", {
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 >= gsettings.SPLASH_DROP_LIFETIME then
self.object:remove()
end
end
end
})]]
minetest.register_on_shutdown(function()
for i, player in ipairs(minetest.get_connected_players()) do
player:get_meta():set_string("is_shooting", "")
end
end)
minetest.register_globalstep(function(dtime)
gun.global_step_through_players_with_guns()

View File

@ -1,5 +1,6 @@
local modpath = minetest.get_modpath("portaltest")
dofile(modpath .. "/aerial_faith_plate.lua")
dofile(modpath .. "/config.lua")
dofile(modpath .. "/gun.lua")
dofile(modpath .. "/panels.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.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 467 B

After

Width:  |  Height:  |  Size: 467 B

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB