267 lines
7.7 KiB
Lua
267 lines
7.7 KiB
Lua
local modpath = core.get_modpath(core.get_current_modname())
|
|
local shared = {
|
|
registered_rifles = {},
|
|
}
|
|
local player_cooldowns = {}
|
|
core.register_on_joinplayer(function(player, last_login) player_cooldowns[player:get_player_name()] = 0 end)
|
|
core.register_on_leaveplayer(function(player, timed_out) player_cooldowns[player:get_player_name()] = nil end)
|
|
local S = core.get_translator(core.get_current_modname())
|
|
shared.S = S
|
|
if core.global_exists("armor") and armor.attributes then
|
|
table.insert(armor.attributes, "bullet_res")
|
|
table.insert(armor.attributes, "ammo_save")
|
|
table.insert(armor.attributes, "ranged_dmg")
|
|
end
|
|
|
|
local function create_quaternion(axis, angle)
|
|
local half_angle = angle / 2
|
|
local sin_half_angle = math.sin(half_angle)
|
|
local cos_half_angle = math.cos(half_angle)
|
|
|
|
return {
|
|
w = cos_half_angle,
|
|
x = axis.x * sin_half_angle,
|
|
y = axis.y * sin_half_angle,
|
|
z = axis.z * sin_half_angle,
|
|
}
|
|
end
|
|
|
|
local function rotate_by_quaternion(v, q)
|
|
local xx = q.x * q.x
|
|
local yy = q.y * q.y
|
|
local zz = q.z * q.z
|
|
local xy = q.x * q.y
|
|
local xz = q.x * q.z
|
|
local yz = q.y * q.z
|
|
local wx = q.w * q.x
|
|
local wy = q.w * q.y
|
|
local wz = q.w * q.z
|
|
|
|
return {
|
|
x = (1 - 2 * (yy + zz)) * v.x + (2 * (xy - wz)) * v.y + (2 * (xz + wy)) * v.z,
|
|
y = (2 * (xy + wz)) * v.x + (1 - 2 * (xx + zz)) * v.y + (2 * (yz - wx)) * v.z,
|
|
z = (2 * (xz - wy)) * v.x + (2 * (yz + wx)) * v.y + (1 - 2 * (xx + yy)) * v.z,
|
|
}
|
|
end
|
|
|
|
local function deviate(dir, max_deviation)
|
|
local axis = vector.normalize(vector.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5))
|
|
local angle = math.random() * max_deviation
|
|
local quaternion = create_quaternion(axis, angle)
|
|
return rotate_by_quaternion(dir, quaternion)
|
|
end
|
|
|
|
shared.deviate = deviate
|
|
|
|
shared.register_rifle = function (name, def)
|
|
accuracy.register(name)
|
|
shared.registered_rifles[name] = true
|
|
core.register_tool(name, def)
|
|
end
|
|
|
|
local function shoot_powergun(itemstack, player, pointed_thing)
|
|
local PowerCaps = itemstack:get_definition()._rifle_traits
|
|
|
|
local cooldown = PowerCaps.cooldown or 0
|
|
local consumption = PowerCaps.consumption or 0
|
|
|
|
local inv = player:get_inventory()
|
|
|
|
if
|
|
inv:contains_item("main", "powerguns:power " .. PowerCaps.consumption) and
|
|
player_cooldowns[player:get_player_name()] < os.clock()
|
|
then
|
|
player_cooldowns[player:get_player_name()] = os.clock() + cooldown
|
|
|
|
local shoot_sound = PowerCaps.sound
|
|
local initial_speed = PowerCaps.velocity or 20
|
|
local projNum = PowerCaps.projectiles or 1
|
|
local mobPen = PowerCaps.mob_penetration or 0
|
|
local nodePen = PowerCaps.node_penetration or 0
|
|
local power_durability = PowerCaps.durability or 0
|
|
local gravity = PowerCaps.gravity or 0
|
|
local door_breaking = PowerCaps.door_breaking or 0
|
|
local projEnt = PowerCaps.entity or "powerguns:shot_bullet"
|
|
local visualType = PowerCaps.visual or "wielditem"
|
|
local texture = PowerCaps.texture or "powerguns:shot_bullet_visual"
|
|
local ignite = PowerCaps.ignites_explosives or 0
|
|
local size = PowerCaps.projectile_size or 0.0025
|
|
|
|
|
|
local _rifle_traits = itemstack:get_definition()._rifle_traits
|
|
local pos = player:get_pos()
|
|
pos.y = pos.y + player:get_properties().eye_height
|
|
local dir = player:get_look_dir()
|
|
local yaw = player:get_look_horizontal()
|
|
local svertical = player:get_look_vertical()
|
|
|
|
if pos and dir and yaw then
|
|
core.sound_play(shoot_sound, {pos = pos, max_hear_distance = 500}, true)
|
|
local user = player
|
|
local projectiles = projNum or 1
|
|
|
|
|
|
|
|
|
|
local deviated_dir = deviate(user:get_look_dir(),accuracy.get(player)/2)
|
|
|
|
for i = 1, projectiles do
|
|
local obj = core.add_entity(pos, "powerguns:shot_bullet")
|
|
local ent = obj:get_luaentity()
|
|
|
|
local deviated_dir = deviate(deviated_dir,(1-(PowerCaps.accuracy or 100)/100)/2)
|
|
local velocity = vector.multiply(deviated_dir, initial_speed)
|
|
|
|
obj:set_properties(
|
|
{
|
|
textures = {texture},
|
|
visual = visualType,
|
|
collisionbox = {-size, -size, -size, size, size, size},
|
|
glow = 20
|
|
}
|
|
)
|
|
ent.owner = player:get_player_name()
|
|
if obj then
|
|
ent.damage = _rifle_traits.damage
|
|
ent.ignite = ignite
|
|
ent.size = size
|
|
ent.timer = 0 + (initial_speed / 2000)
|
|
ent.wear = 0
|
|
obj:set_velocity(velocity)
|
|
obj:set_acceleration({x = 0, y = -gravity, z = 0})
|
|
obj:set_rotation(vector.new(0, (math.atan2(deviated_dir.z, deviated_dir.x) - math.pi)%(math.pi*2), -svertical))
|
|
end
|
|
end
|
|
end
|
|
if core.settings:get_bool("rifles.gun_wear", true) then
|
|
itemstack:add_wear(65535 / power_durability)
|
|
end
|
|
|
|
inv:remove_item("main", "powerguns:power " .. PowerCaps.consumption)
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
core.register_craftitem("powerguns:power", {
|
|
description = S("Power Particle"),
|
|
stack_max = 10000,
|
|
inventory_image = "powerguns_power.png",
|
|
})
|
|
|
|
assert(loadfile(modpath .. "/ammo.lua"))(shared)
|
|
assert(loadfile(modpath .. "/crafting.lua"))(shared)
|
|
|
|
assert(loadfile(modpath .. "/forcegun.lua"))(shared)
|
|
assert(loadfile(modpath .. "/generator.lua"))(shared)
|
|
|
|
local players_shooting_automatic = {}
|
|
|
|
core.register_globalstep(function(dtime)
|
|
for i = #players_shooting_automatic, 1, -1 do
|
|
local playername = players_shooting_automatic[i]
|
|
local player = core.get_player_by_name(playername)
|
|
if player and player:get_player_control().dig and player:get_hp() > 0 then
|
|
local itemstack = player:get_wielded_item()
|
|
if itemstack:get_name() == "powerguns:rifle" and player_cooldowns[playername] < os.clock() then
|
|
player:set_wielded_item(shoot_powergun(itemstack, player))
|
|
end
|
|
else
|
|
table.remove(players_shooting_automatic, i)
|
|
end
|
|
end
|
|
end)
|
|
|
|
local function start_automatic(itemstack, user, pointed_thing)
|
|
local name = user:get_player_name()
|
|
for _,v in ipairs(players_shooting_automatic) do
|
|
if v == name then return end
|
|
end
|
|
table.insert(players_shooting_automatic, name)
|
|
end
|
|
|
|
core.register_craftitem("powerguns:blue_ray_visual", {
|
|
wield_scale = {x=1.75,y=1.75,z=1.75},
|
|
inventory_image = "powerguns_blue_ray.png",
|
|
})
|
|
|
|
shared.register_rifle("powerguns:pistol", {
|
|
stack_max= 1,
|
|
wield_scale = {x=1.15,y=1.15,z=1.15},
|
|
description = S("Power Pistol"),
|
|
range = 0,
|
|
inventory_image = "powerguns_pistol.png",
|
|
_rifle_traits = {
|
|
damage = {fleshy=15,knockback=0},
|
|
velocity = 65,
|
|
accuracy = 100,
|
|
cooldown = 0.3,
|
|
projectiles = 1,
|
|
durability = 5000,
|
|
sound = "powerguns_laser",
|
|
door_breaking = 1,
|
|
mob_penetration = 50,
|
|
consumption = 10,
|
|
visual = "wielditem",
|
|
texture = "powerguns:blue_ray_visual",
|
|
projectile_size = 0.1,
|
|
ignites_explosives = 1,
|
|
},
|
|
on_use = shoot_powergun,
|
|
})
|
|
|
|
core.register_craftitem("powerguns:red_ray_visual", {
|
|
wield_scale = {x=1.5,y=1.5,z=2.0},
|
|
inventory_image = "powerguns_red_ray.png",
|
|
})
|
|
|
|
shared.register_rifle("powerguns:rifle", {
|
|
wield_scale = {x=1.9,y=1.9,z=2.5},
|
|
description = S("Power Rifle"),
|
|
range = 0,
|
|
_rifle_traits = {
|
|
damage = {fleshy=12,knockback=0},
|
|
velocity = 60,
|
|
accuracy = 100,
|
|
cooldown = 0.2,
|
|
projectiles = 1,
|
|
durability = 12500,
|
|
sound = "powerguns_laser",
|
|
door_breaking = 1,
|
|
mob_penetration = 40,
|
|
consumption = 8,
|
|
visual = "wielditem",
|
|
texture = "powerguns:red_ray_visual",
|
|
projectile_size = 0.075,
|
|
ignites_explosives = 1,
|
|
},
|
|
inventory_image = "powerguns_rifle.png",
|
|
on_use = start_automatic,
|
|
})
|
|
|
|
shared.register_rifle("powerguns:shotgun", {
|
|
stack_max= 1,
|
|
wield_scale = {x=2.0,y=2.0,z=1.75},
|
|
description = S("Power Shotgun"),
|
|
range = 0,
|
|
inventory_image = "powerguns_shotgun.png",
|
|
_rifle_traits = {
|
|
damage = {fleshy=10,knockback=0},
|
|
velocity = 55,
|
|
accuracy = 40,
|
|
cooldown = 0.5,
|
|
durability = 2000,
|
|
sound = "powerguns_laser",
|
|
door_breaking = 1,
|
|
mob_penetration = 40,
|
|
consumption = 30,
|
|
visual = "sprite",
|
|
texture = "powerguns_green_ray.png",
|
|
projectile_size = 0.005,
|
|
projectiles = 6,
|
|
ignites_explosives = 1,
|
|
},
|
|
on_use = shoot_powergun,
|
|
})
|
|
|
|
|