243 lines
7.8 KiB
Lua
243 lines
7.8 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
|
|
|
|
local modstorage = core.get_mod_storage()
|
|
yl_snowball.modstorage = modstorage
|
|
|
|
|
|
local get_player_participation = yl_snowball.get_player_participation
|
|
|
|
yl_snowball.COOLDOWN = 0.4 -- TODO make configurable
|
|
|
|
yl_snowball.SNOWBALL_SPEED = 17 -- 17 was good
|
|
yl_snowball.SNOWBALL_GRAVITY = -8 -- -8 was good
|
|
|
|
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 = core.get_us_time() --core.get_gametime() -- gametime seems to "lag"?
|
|
local diff = current_time - (player_last_throw_time[player_name] or 0)
|
|
if diff < yl_snowball.COOLDOWN * 1000000 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 gravity = yl_snowball.SNOWBALL_GRAVITY
|
|
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, gravity, 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
|
|
|
|
|
|
|
|
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 = {
|
|
punch = {
|
|
tool_capabilities = {
|
|
damage_groups = { fleshy = 1.0 },
|
|
},
|
|
},
|
|
|
|
particles = {
|
|
amount = 1,
|
|
time = 0.1,
|
|
--time = 4,
|
|
texture = "yl_snowball_snowflake.png",
|
|
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 I think enabling this will allow jumping on them?
|
|
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_step = function(self, dtime, moveresult)
|
|
-- draw a snowflake trail
|
|
ballistics.on_step_particles(self, dtime, moveresult)
|
|
end,
|
|
|
|
on_hit_node = function(self, node_pos, node, above_pos, intersection_point, intersection_normal, box_id)
|
|
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)
|
|
|
|
if y_bows and y_bows.util.bullseye_was_hit(self, node_pos, node, above_pos,
|
|
intersection_point, intersection_normal,
|
|
box_id) then
|
|
y_bows.on_bullseye_hit(node_pos, self._source_obj)
|
|
end
|
|
|
|
return true
|
|
end,
|
|
|
|
on_hit_object = function(self, target, intersection_point, intersection_normal, box_id)
|
|
spawn_snow_puff(intersection_point, intersection_normal)
|
|
ballistics.on_hit_object_hit_sound_play(self, target, intersection_point, intersection_normal, box_id)
|
|
self.object:remove()
|
|
|
|
if futil.is_player(target) then
|
|
local target_name = target:get_player_name()
|
|
local source = self._source_obj
|
|
if futil.is_player(source) then
|
|
local source_name = source:get_player_name()
|
|
|
|
local source_participates = get_player_participation(source_name)
|
|
local target_participates = get_player_participation(target_name)
|
|
|
|
-- register hit and play sounds only if both participate
|
|
if source_participates and target_participates then
|
|
|
|
yl_snowball.snowgame.register_hit(source_name, target_name)
|
|
|
|
local sound_name = "y_bows_arrow_successful_hit"
|
|
core.sound_play({ name = sound_name }, {
|
|
gain = 0.7,
|
|
to_player = source_name,
|
|
})
|
|
local take_hit_sound_name = "default_snow_footstep"
|
|
core.sound_play({ name = take_hit_sound_name }, {
|
|
gain = 0.7,
|
|
to_player = target_name,
|
|
})
|
|
end
|
|
end
|
|
else
|
|
ballistics.on_hit_object_punch(self, target, intersection_point, intersection_normal, box_id)
|
|
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'},
|
|
})
|