213 lines
6.4 KiB
Lua
213 lines
6.4 KiB
Lua
local v_new = vector.new
|
|
local v_rotate_around_axis = vector.rotate_around_axis
|
|
local v_multiply = vector.multiply
|
|
local v_dot = vector.dot
|
|
|
|
|
|
yl_snowball.COOLDOWN = 0.1 -- TODO make configurable
|
|
|
|
yl_snowball.SNOWBALL_SPEED = 17
|
|
|
|
local player_last_throw_time = {}
|
|
|
|
core.register_on_leaveplayer(
|
|
function(player, _timed_out)
|
|
local player_name = player:get_player_name()
|
|
if player_name ~= "" then
|
|
player_last_throw_time[player_name] = nil
|
|
end
|
|
end
|
|
)
|
|
|
|
|
|
local function spawn_snow_puff(pos, normal)
|
|
local shift = normal * 0.1
|
|
local center = pos + shift
|
|
local def = {
|
|
pos = center,
|
|
amount = 20,
|
|
time = 0.01,
|
|
radius = { min = 0.01, max = 0.1, bias = -1 },
|
|
drag = 0.1,
|
|
attract = {
|
|
kind = "point",
|
|
strength = -14,
|
|
origin = center - shift,
|
|
},
|
|
acc = v_new(0, -8, 0),
|
|
exptime = 0.5,
|
|
size = 2,
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
texture = {
|
|
name = "yl_snowball_snowflake.png",
|
|
--blend = "clip", -- does not work in 5.9?!?
|
|
},
|
|
--glow = 2,
|
|
}
|
|
core.add_particlespawner(def)
|
|
end
|
|
|
|
|
|
local function get_start_params(player)
|
|
local look = player:get_look_dir()
|
|
local eye_height = v_new(0, player:get_properties().eye_height, 0)
|
|
local eye_offset = player:get_eye_offset() * 0.1 -- Eye offset is in scaled coords
|
|
local yaw = player:get_look_horizontal()
|
|
local dir = v_multiply(look, 0.4) -- forward shift. TODO tweak constant
|
|
local p_pos = player:get_pos()
|
|
local up = v_new(0,1,0)
|
|
-- Initial projectile position: in front of camera, shifted little forward
|
|
local start = p_pos + eye_height + v_rotate_around_axis(eye_offset, up, yaw) + dir
|
|
|
|
local player_vel = futil.get_velocity(player)
|
|
-- vector pointing right
|
|
local right = v_rotate_around_axis(v_new(1,0,0), up, yaw)
|
|
-- horizonal velocity component
|
|
local horiz_vel = v_multiply(right, v_dot(player_vel, right))
|
|
-- Make projectile velocity influenced only by forward/back and up/down movement.
|
|
-- This makes you always shoot "straight"
|
|
local vel = player_vel - horiz_vel
|
|
|
|
-- vizlib.draw_line(p_pos, p_pos + v_multiply(player_vel,1.0)) -- velocity
|
|
-- vizlib.draw_line(p_pos, p_pos + v_multiply(look,3), {color = "green"}) -- look dir
|
|
-- vizlib.draw_line(p_pos, p_pos + v_multiply(vel,1.0), {color = "yellow"}) -- projectile vel
|
|
|
|
return start, look, vel
|
|
end
|
|
|
|
|
|
-- FIXME make this local
|
|
yl_snowball.on_use = function(itemstack, user, pointed_thing)
|
|
if (not user) or (not user:is_player()) then
|
|
return itemstack
|
|
end
|
|
local player = user
|
|
local player_name = player:get_player_name()
|
|
|
|
local current_time = os.clock() --core.get_gametime() -- gametime seems to "lag"?
|
|
if current_time - (player_last_throw_time[player_name] or 0) < yl_snowball.COOLDOWN then
|
|
-- too soon, don't shot, don't take items
|
|
return nil
|
|
end
|
|
|
|
player_last_throw_time[player_name] = current_time
|
|
|
|
local speed = yl_snowball.SNOWBALL_SPEED
|
|
local start, look, p_vel = get_start_params(player)
|
|
-- projectile velocity points where we look + affected by player movement
|
|
local vel = (look * speed) + (p_vel * 0.3)
|
|
|
|
ballistics.shoot(
|
|
"yl_snowball:snowball_ent",
|
|
start,
|
|
vel,
|
|
v_new(0, -8, 0),
|
|
player,
|
|
nil
|
|
)
|
|
|
|
yl_snowball.snowgame.register_shot(player_name)
|
|
|
|
if not core.check_player_privs(player, "creative") then
|
|
itemstack:take_item(1)
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
|
|
if not yl_snowball._registered then -- FIXME remove this
|
|
yl_snowball._registered = true -- register only on load
|
|
|
|
core.register_craftitem(
|
|
"yl_snowball:snowball",
|
|
{
|
|
description = "Throwable Snowball",
|
|
stack_max= 99,
|
|
inventory_image = "yl_snowball.png",
|
|
on_use = function(...) -- FIXME remove wrapper
|
|
return yl_snowball.on_use(...)
|
|
end,
|
|
}
|
|
)
|
|
|
|
local SIZE = 0.4
|
|
local SNOWBALL_DEF = {
|
|
parameters = {
|
|
particles = {
|
|
amount = 1,
|
|
time = 0.1,
|
|
--time = 4,
|
|
texture = "yl_snowball_snowflake.png",
|
|
animation = {
|
|
type = "vertical_frames",
|
|
aspect_w = 8,
|
|
aspect_h = 8,
|
|
length = 1,
|
|
},
|
|
glow = 1,
|
|
minvel = { x = 0, y = -0.1, z = 0 },
|
|
maxvel = { x = 0, y = -0.1, z = 0 },
|
|
minacc = { x = 0, y = -0.1, z = 0 },
|
|
maxacc = { x = 0, y = -0.1, z = 0 },
|
|
minexptime = 0.5,
|
|
maxexptime = 0.5,
|
|
minsize = 2,
|
|
maxsize = 2,
|
|
--_period = 0.09,
|
|
_period = 0.2,
|
|
},
|
|
hit_sound = {
|
|
spec = { name = "default_place_node" },
|
|
parameters = { gain = 0.8, pitch = 2.0 },
|
|
},
|
|
},
|
|
physical = false, -- FIXME ???
|
|
visual = "sprite",
|
|
visual_size = {x=SIZE, y=SIZE},
|
|
textures = {'yl_snowball.png'},
|
|
collisionbox = {-SIZE/2, -SIZE/2, -SIZE/2, SIZE/2, SIZE/2, SIZE/2},
|
|
-- on_activate = function(self, staticdata)
|
|
-- self.object:remove()
|
|
-- end,
|
|
|
|
on_step = function(self, dtime, moveresult)
|
|
--print(dump(dtime), dump(dtime), dump(moveresult))
|
|
ballistics.on_step_particles(self, dtime, moveresult)
|
|
end,
|
|
|
|
on_hit_node = function(self, node_pos, node, above_pos, intersection_point, intersection_normal, box_id)
|
|
--print(dump(node_pos), dump(node))
|
|
ballistics.on_hit_node_hit_sound_play(self, node_pos, node, above_pos, intersection_point, intersection_normal, box_id)
|
|
self.object:remove()
|
|
spawn_snow_puff(intersection_point, intersection_normal)
|
|
return true
|
|
end,
|
|
|
|
on_hit_object = function(self, target, intersection_point, intersection_normal, box_id)
|
|
-- core.chat_send_all(('%s hit %s'):format(os.clock(), dump(target:get_entity_name())))
|
|
-- print(dump(self))
|
|
spawn_snow_puff(intersection_point, intersection_normal)
|
|
self.object:remove()
|
|
|
|
if target:is_player() then
|
|
local target_name = target:get_player_name()
|
|
yl_snowball.snowgame.register_hit(self._source_player_name, target_name)
|
|
end
|
|
|
|
return true
|
|
end
|
|
}
|
|
|
|
|
|
ballistics.register_projectile("yl_snowball:snowball_ent", SNOWBALL_DEF)
|
|
|
|
|
|
core.register_craft({
|
|
type = "shapeless",
|
|
output = 'yl_snowball:snowball 3',
|
|
recipe = {'default:snow'},
|
|
})
|
|
|
|
end
|