Includes Changes such as:

First Exotic Class weapon: Minigun
Changes to Energy/Magless weapon cooling.
Brand new server introduction.
Major HUD rework.
Brand new auth handler.
Modified default player physics.
Clean up of code from init.lua to relevant files.
fps_game
Jordan Snelling 2021-02-06 02:44:45 +00:00
parent 8046c385fa
commit 795a0d6f6b
20 changed files with 679 additions and 205 deletions

10
.gitignore vendored
View File

@ -1,10 +1,14 @@
## Specially ignored directories:
mods/test
mods/weapons/sounds
mods/persistence/db/weapons_player_auth.prs
mods/persistence/db/weapons_player_data.prs
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
mods/test
mods/weapons/sounds
# Icon must end with two \r
Icon
@ -28,4 +32,4 @@ Network Trash Folder
Temporary Items
.apdisk
.vs/slnx.sqlite
.vs
.vs

View File

@ -6,4 +6,14 @@ active_object_send_range_blocks = 5
active_block_range = 5
ask_reconnect_on_crash = true
player_transfer_distance = 128
max_objects_per_block = 512
max_objects_per_block = 512
movement_acceleration_default = 4.45
movement_acceleration_air = 1.55
movement_speed_walk = 5.25
movement_speed_crouch = 0.95
movement_speed_climb = 1.25
movement_speed_jump = 7
movement_liquid_fluidity = 0.65
movement_liquid_fluidity_smooth = 0.75
movement_liquid_sink = 0

View File

@ -0,0 +1 @@
This file is just to ensure Git properly includes this directory as Minetest will crash on attempting to access a non-existent folder.

View File

@ -1 +0,0 @@
return {["archfan"] = {["ammo_scale"] = 1, ["offsets"] = {["killfeed"] = {["y"] = 0, ["x"] = 0}, ["hp"] = {["y"] = 0, ["x"] = 0}, ["ammo"] = {["y"] = 0, ["x"] = 0}, ["score"] = {["y"] = 0, ["x"] = 0}}, ["hp_scale"] = 1, ["nick"] = "Gandalf"}, ["Emerald"] = {["ammo_scale"] = 1, ["offsets"] = {["killfeed"] = {["y"] = 0, ["x"] = 0}, ["hp"] = {["y"] = 0, ["x"] = 0}, ["ammo"] = {["y"] = 0, ["x"] = 0}, ["score"] = {["y"] = 0, ["x"] = 0}}, ["hp_scale"] = 1, ["nick"] = "Emerald"}, ["Jordach"] = {["ammo_scale"] = 1, ["offsets"] = {["killfeed"] = {["y"] = 0, ["x"] = 0}, ["hp"] = {["y"] = 0, ["x"] = 0}, ["ammo"] = {["y"] = 0, ["x"] = 0}, ["score"] = {["y"] = 0, ["x"] = 0}}, ["hp_scale"] = 1, ["nick"] = "NotJordach"}}

View File

@ -18,52 +18,75 @@ solarsail.color = {}
solarsail.util = {}
solarsail.util.clipboard = {}
solarsail.util.functions = {}
solarsail.avg_dtime = 0
solarsail.last_dtime = {}
-- Handle flat mapgen, for building a world
local dtime_steps = 0
local num_steps = 30*2
minetest.register_globalstep(function(dtime)
if dtime_steps == num_steps then
local avg = 0
for i=1, num_steps do
avg = avg + solarsail.last_dtime[i]
end
solarsail.avg_dtime = avg / num_steps
dtime_steps = 0
solarsail.last_dtime[1] = dtime
--print(string.format("%.4f", tostring(solarsail.avg_dtime)))
else
dtime_steps = dtime_steps + 1
solarsail.last_dtime[dtime_steps] = dtime
end
end)
minetest.register_node("solarsail:wireframe", {
description = "Wireframe, prototyping node",
tiles = {"solarsail_wireframe.png"},
groups = {debug=1}
})
if true then
-- Handle flat mapgen, for building a world
minetest.register_node("solarsail:wireframe", {
description = "Wireframe, prototyping node",
tiles = {"solarsail_wireframe.png"},
groups = {debug=1}
})
--minetest.register_alias("mapgen_stone", "solarsail:wireframe")
--minetest.register_alias("mapgen_grass", "solarsail:wireframe")
--minetest.register_alias("mapgen_water_source", "solarsail:wireframe")
--minetest.register_alias("mapgen_river_water_source", "solarsail:wireframe")
-- Sava data handling (per-player):
dofile(minetest.get_modpath("solarsail").."/save.lua")
-- HSVA->RGBA->HSVA handling:
dofile(minetest.get_modpath("solarsail").."/colour.lua")
-- HUD rendering and formspec handling:
dofile(minetest.get_modpath("solarsail").."/hud.lua")
-- Cameras used in dialog, cutscenes or when controlled by the player:
--dofile(minetest.get_modpath("solarsail").."/camera.lua")
-- Start skybox engine:
--dofile(minetest.get_modpath("solarsail").."/skybox.lua")
-- Control handling for HUDs, player entity, etc:
dofile(minetest.get_modpath("solarsail").."/control.lua")
-- Third person player camera handling + third person model:
dofile(minetest.get_modpath("solarsail").."/player.lua")
-- Basic, advanced NPC AI;
--dofile(minetest.get_modpath("solarsail").."/npc.lua")
-- Player menus:
--dofile(minetest.get_modpath("solarsail").."/menu.lua")
end
--minetest.register_alias("mapgen_stone", "solarsail:wireframe")
--minetest.register_alias("mapgen_grass", "solarsail:wireframe")
--minetest.register_alias("mapgen_water_source", "solarsail:wireframe")
--minetest.register_alias("mapgen_river_water_source", "solarsail:wireframe")
-- Sava data handling (per-player):
dofile(minetest.get_modpath("solarsail").."/save.lua")
-- HSVA->RGBA->HSVA handling:
dofile(minetest.get_modpath("solarsail").."/colour.lua")
-- HUD rendering and formspec handling:
dofile(minetest.get_modpath("solarsail").."/hud.lua")
-- Cameras used in dialog, cutscenes or when controlled by the player:
--dofile(minetest.get_modpath("solarsail").."/camera.lua")
-- Start skybox engine:
--dofile(minetest.get_modpath("solarsail").."/skybox.lua")
-- Control handling for HUDs, player entity, etc:
dofile(minetest.get_modpath("solarsail").."/control.lua")
-- Third person player camera handling + third person model:
dofile(minetest.get_modpath("solarsail").."/player.lua")
-- Basic, advanced NPC AI;
--dofile(minetest.get_modpath("solarsail").."/npc.lua")
-- Player menus:
--dofile(minetest.get_modpath("solarsail").."/menu.lua")

106
mods/weapons/auth.lua Normal file
View File

@ -0,0 +1,106 @@
-- Authentication module for Battle for Arkhos
-- License RESERVED
-- Author Jordach
weapons.auth = nil
local sudo_invoked = false
local function rst_sudo()
sudo_invoked = false
end
local function grant_sudo_privs(name)
-- Grants admins all privs for temporary reasons; these are not permanent.
if name == minetest.settings:get("name") then
local privs = {}
for priv, def in pairs(core.registered_privileges) do
privs[priv] = true
end
sudo_invoked = true
minetest.set_player_privs(name, privs)
minetest.after(0.2, rst_sudo)
return true
end
return false
end
if true then
local loaded, wad, file_created = persistence.load_data("weapons_player_auth", true)
weapons.auth = table.copy(wad)
wad = nil
end
weapons.auth_handler = {
get_auth = function(name)
-- I really doubt this as it's loaded from a persistence db; as it creates an empty table.
if weapons.auth == nil then
return nil
elseif weapons.auth[name] == nil then
return nil
else
return weapons.auth[name]
end
end,
create_auth = function(name, password)
weapons.auth[name] = {}
weapons.auth[name].password = password
weapons.auth[name].privileges = {}
weapons.auth[name].privileges.shout = true
weapons.auth[name].privileges.interact = true
weapons.auth[name].last_login = tonumber(os.time())
persistence.save_data("weapons_player_auth", weapons.auth)
end,
delete_auth = function(name)
weapons.auth[name] = {}
persistence.save_data("weapons_player_auth", weapons.auth)
return true
end,
set_password = function(name, password)
weapons.auth[name].password = password
persistence.save_data("weapons_player_auth", weapons.auth)
return true
end,
set_privileges = function(name, privileges)
weapons.auth[name].privileges = privileges
if not sudo_invoked then
persistence.save_data("weapons_player_auth", weapons.auth)
end
return true
end,
reload = function()
return true
end,
record_login = function(name)
weapons.auth[name].last_login = tonumber(os.time())
persistence.save_data("weapons_player_auth", weapons.auth)
return true
end,
iterate = function()
return pairs(weapons.auth)
end
}
minetest.register_authentication_handler(weapons.auth_handler)
minetest.log("action", "[Weapons] weapons/auth.lua registered and loaded authentication for world-persistent logins.")
minetest.register_chatcommand("sudo", {
--params = "N/A",
description = "Grants the username as defined in minetest.conf temporary admin privs.",
func = function(name)
if grant_sudo_privs(name) then
minetest.log("warning", name .. " has been granted temporary privs.")
return true, "Temporary admin and server privs granted. With great power, comes great responsibility."
else
minetest.log("warning", name .. " is not in the minetest.conf. This incident will be reported.")
return false, weapons.get_nick(minetest.get_player_by_name(name)) .. " is not in the minetest.conf. This incident will be reported."
end
end,
})

View File

@ -81,8 +81,10 @@ local function conv_heat_to_rpm(weapon, player)
local mult = weapon._accel_mult or 1
if current_heat == nil then
return 1
elseif current_heat > 0 then
return (current_heat/100) + mult
elseif current_heat > 99 then
return 1
elseif current_heat < 100 then
return solarsail.util.functions.remap(current_heat, 0, 100, 1, weapon._accel_mult)
else
return 1
end

View File

@ -13,6 +13,72 @@ function weapons.get_nick(player)
end
end
--[[
solarsail.util.functions.convert_from_hex()
input = ColorSpec
returns three variables red, green and blue in base 10 values.
]]--
function solarsail.util.functions.convert_from_hex(input)
local r, g, b = input:match("^#(%x%x)(%x%x)(%x%x)")
return tonumber(r, 16), tonumber(g, 16), tonumber(b, 16)
end
--[[
solarsail.util.functions.lerp()
var_a = input number to blend from. (at ratio 0)
var_b = input number to blend to. (at ratio 1)
returns the blended value depending on ratio.
]]--
function solarsail.util.functions.lerp(var_a, var_b, ratio)
return (1-ratio)*var_a + (ratio*var_b)
end
--[[
solarsail.util.functions.remap()
val = Input value
min_val = minimum value of your expected range
max_val = maximum value of your expected range
min_map = minimum value of your remapped range
max_map = maximum value of your remapped range
returns a value between min_map and max_map based on where val is relative to min_val and max_val.
]]
function solarsail.util.functions.remap(val, min_val, max_val, min_map, max_map)
return (val-min_val)/(max_val-min_val) * (max_map-min_map) + min_map
end
--[[
solarsail.util.functions.blend_colours()
val = Input Value
min_val = Minimum value (values less than this are capped)
max_val = Maximum value (values more than this are capped)
min_col = ColorSpec defining the colour of the minimum value.
returns a ColorSpec blended or capped as one of the two input colours.
]]--
function solarsail.util.functions.blend_colours(val, min_val, max_val, min_col, max_col)
if val <= min_val then
return min_col
elseif val >= max_val then
return max_col
end
local min_r, min_g, min_b = solarsail.util.functions.convert_from_hex(min_col)
local max_r, max_g, max_b = solarsail.util.functions.convert_from_hex(max_col)
local blend = solarsail.util.functions.remap(val, min_val, max_val, 0, 1)
local res_r = solarsail.util.functions.lerp(min_r, max_r, blend)
local res_g = solarsail.util.functions.lerp(min_g, max_g, blend)
local res_b = solarsail.util.functions.lerp(min_b, max_b, blend)
return minetest.rgba(res_r, res_g, res_b)
end
function solarsail.util.functions.y_direction(rads, recoil)
return math.sin(rads) * recoil
end

View File

@ -112,7 +112,8 @@ local function get_ammo_appearances(player, weapon)
local over_string = "hud_bar_overlay.png^[opacity:127"
local weapon = minetest.registered_nodes[player:get_wielded_item():get_name()]
local is_thermal = false
if weapon._is_energy == nil then
if weapon == nil then
elseif weapon._is_energy == nil then
elseif weapon._is_energy then
is_thermal = true
end

View File

@ -19,7 +19,10 @@ if true then
wpd = nil
end
-- Special, load the additions to the solarsail global before anything else.
-- Handle world persistent login as we delete worlds between games.
dofile(minetest.get_modpath("weapons").."/auth.lua")
-- Special usecase, load the additions to the solarsail global before anything else.
-- Ideally, this should be at the bottom with the others, but we make do.
dofile(minetest.get_modpath("weapons").."/functions.lua")
@ -71,7 +74,7 @@ end
function core.send_leave_message(player_name, timed_out)
local msg = weapons.team_colourize(minetest.get_player_by_name(player_name), weapons.player_data[player_name].nick) .. " left the game"
if timed_out then
msg = msg .. ", due to network error."
msg = msg .. ", due to network interruption or error."
else
msg = msg .. "."
end
@ -102,9 +105,41 @@ function core.get_server_status(player_name, joined)
if num < #nplayers then
status = status .. weapons.team_colourize(nplayers[num].user, nplayers[num].nick) .. ", "
else
status = status .. weapons.team_colourize(nplayers[num].user, nplayers[num].nick) .. "."
status = status .. weapons.team_colourize(nplayers[num].user, nplayers[num].nick) .. ".\n"
end
end
if solarsail.avg_dtime == nil or solarsail.avg_dtime == 0 then
local _chance = math.random(1, 100)
local _msg = "Excuse me, but why are you launching the server as a client?"
print(_chance)
if _chance < 11 then
-- https://discord.com/channels/369122544273588224/369122544273588226/807084993854701608
-- From @ElCeejus
_msg = "Excuse me bruv? Why are yeh laoonching Minetaest hes a client yeh? Kinda schtewpid innit?"
end
status = status .. minetest.colorize("#ff0000", _msg)
else
status = status .. "Average Server Lag: " ..
minetest.colorize(
solarsail.util.functions.blend_colours(
solarsail.avg_dtime,
0.03,
0.12,
"#00ff00",
"#ff0000"
),
string.format("%.2f", tostring(solarsail.avg_dtime)) .. "s"
)
end
if weapons.auth[player_name] == nil then
elseif weapons.auth[player_name].last_login == nil then
else
local date = os.date("%Y/%m/%d %H:%M:%S", weapons.auth[player_name].last_login)
status = status .. "\nLast Join: " ..
minetest.colorize(weapons.teams.no_team, date)
end
return status
end
@ -297,9 +332,11 @@ dofile(minetest.get_modpath("weapons").."/weapons/blocks.lua")
dofile(minetest.get_modpath("weapons").."/weapons/assault_rifle.lua")
dofile(minetest.get_modpath("weapons").."/weapons/burst_rifle.lua")
dofile(minetest.get_modpath("weapons").."/weapons/sniper_rifle.lua")
dofile(minetest.get_modpath("weapons").."/weapons/scout_rifle.lua")
dofile(minetest.get_modpath("weapons").."/weapons/veteran_rifle.lua")
dofile(minetest.get_modpath("weapons").."/weapons/auto_shotgun.lua")
dofile(minetest.get_modpath("weapons").."/weapons/plasma_autorifle.lua")
dofile(minetest.get_modpath("weapons").."/weapons/light_machine_gun.lua")
dofile(minetest.get_modpath("weapons").."/weapons/minigun.lua")
--dofile(minetest.get_modpath("weapons").."/weapons/railgun.lua")
--dofile(minetest.get_modpath("weapons").."/weapons/smg.lua")

View File

@ -48,7 +48,9 @@ base_class.items = {
"weapons:sniper_rifle",
"weapons:veteran_rifle",
"weapons:pump_shotgun",
"weapons:light_machine_gun",
"weapons:plasma_autorifle",
"weapons:minigun",
"weapons:pickaxe",
"core:team_neutral"
}

View File

@ -509,7 +509,7 @@ minetest.register_globalstep(function(dtime)
elseif weapon._is_energy then
local ammo = weapon._ammo_type
if not solarsail.controls.player[pname].LMB then
if player_cooldown_timer[pname] > 0.06 then
if player_cooldown_timer[pname] > weapon._cool_timer then
local cng = math.floor(weapons.player_list[pname][ammo] * weapon._cool_rate) - 1
if cng < 0 then cng = 0 end
weapons.player_list[pname][ammo] = cng
@ -518,7 +518,7 @@ minetest.register_globalstep(function(dtime)
player_cooldown_timer[pname] = player_cooldown_timer[pname] + dtime
end
elseif weapons.is_reloading[pname][player:get_wielded_item():get_name()] then
if player_cooldown_timer[pname] > 0.06 then
if player_cooldown_timer[pname] > weapon._cool_timer then
local cng = math.floor(weapons.player_list[pname][ammo] * weapon._cool_rate) - 1
if cng < 0 then cng = 0 end
weapons.player_list[pname][ammo] = cng

View File

@ -164,7 +164,7 @@ Range 150 nodes.]],
_spread_aim = 0.5,
_break_hits = 2,
_block_chance = 50,
_block_chance = 85,
-- Arm Animations + Arm visual settings;
_anim = {

View File

@ -81,7 +81,7 @@ Range 150 nodes.]],
_spread_aim = 0.5,
_break_hits = 2,
_block_chance = 50,
_block_chance = 75,
-- Arm Animations + Arm visual settings;
_anim = {

View File

@ -0,0 +1,101 @@
local function add_extras(player)
local ldir = player:get_look_dir()
local ppos = vector.add(player:get_pos(), vector.new(0, 1.2+ldir.y/3.5, 0))
local px, pz = solarsail.util.functions.yaw_to_vec(player:get_look_horizontal(), 1, false)
ppos = vector.add(ppos, vector.multiply(vector.new(px, 0, pz), 0.225))
local dir = vector.new(pz, 0, -px)
local res = vector.add(ppos, vector.multiply(dir, 0.25))
local ent = minetest.add_entity(res, "weapons:ar_casing")
local pvel = player:get_velocity()
pvel.x = pvel.x/2
pvel.y = pvel.y/2
pvel.z = pvel.z/2
local vel = vector.multiply(vector.new(pz/1.5, ldir.y+1, -px/1.5), 3)
vel = vector.add(vel, vector.new(math.random(-25, 25)/100, 0, math.random(-25, 25)/100))
ent:set_acceleration({x=0, y=-9.80, z=0})
ent:set_velocity(vector.add(pvel, vel))
end
local wep_rpm = 420
local shots_used = 1
weapons.register_weapon("weapons:light_machine_gun", true,
{
-- Config
_type = "gun",
_ammo_type = "lmg",
_slot = "primary",
_localisation = {
itemstring = "weapons:light_machine_gun",
name = "Light Machine Gun",
tooltip =
[[A light machine gun. Good at suppressive fire.
Stats:
20 Damage.
6.65 second reload.
Unaimed spread +- 15 nodes at maximum range.
Aimed spread +- 2 nodes at maximum range.
Range 125 nodes.]],
},
-- HUD / Visual
_tracer = "ar",
_name = "light_machine_gun",
_crosshair = "assault_crosshair.png",
_crosshair_aim = "assault_crosshair.png",
_fov_mult = 0,
_fov_mult_aim = 0.6,
_min_arm_angle = -45,
_max_arm_angle = 75,
_arm_angle_offset = 0,
-- Sounds
_firing_sound = "ass_rifle_fire",
_reload_sound = "ass_rifle_reload",
_casing = "Armature_Casing",
-- Base Stats:
_pellets = 1,
_mag = 100,
_rpm = wep_rpm,
_reload = 6.65,
_speed = 1200,
_range = 125,
_damage = 10,
_movespeed = 0.95,
_movespeed_aim = 0.45,
_shots_used = shots_used,
_recoil = 1.5,
_recoil_vert_min = 2,
_recoil_vert_max = 4.25,
_recoil_hori = 6,
_recoil_factor = 0.8,
_recoil_aim_factor = 0.5,
_spread = 15,
_spread_aim = 2,
_break_hits = 1,
_block_chance = 90,
-- Arm Animations + Arm visual settings;
_anim = {
idle = {x=0, y=0},
idle_fire = {x=0, y=8},
aim = {x=10, y=10},
aim_fire = {x=10, y=18},
reload = {x=60, y=219}
},
_arms = {
mesh = "assault_arms.x",
texture = "assault_rifle.png",
},
on_fire = weapons.raycast_bullet,
on_fire_visual = add_extras,
on_reload = weapons.magazine_reload,
bullet_on_hit = weapons.bullet_on_hit,
})

View File

@ -0,0 +1,254 @@
function apply_recoil(player, weapon, ammo)
local pname = player:get_player_name()
local yaw_rad = player:get_look_horizontal()
local pitch_rad = player:get_look_vertical()
-- Physical knockback; can be canceled out
local result_x, result_z =
solarsail.util.functions.yaw_to_vec(yaw_rad, weapon._recoil, true)
local result_y =
solarsail.util.functions.y_direction(pitch_rad, weapon._recoil)
local pitch_mult = solarsail.util.functions.xz_amount(pitch_rad)
player:add_velocity({
x=result_x * pitch_mult,
y=result_y,
z=result_z * pitch_mult
})
-- Camera recoil; cannot be canceled out
local vert_deg, hori_deg, look_pitch, look_hori = 0
local pammo = weapons.player_list[pname][ammo]
local vert_curve =
solarsail.util.functions.remap(pammo, 0, 100, weapon._recoil_vert_min, weapon._recoil_vert_max)
local hori_curve =
solarsail.util.functions.remap(pammo, 0, 100, weapon._recoil_hori, weapon._recoil_hori_max)
if math.random(0, 1) == 1 then
hori_curve = -hori_curve
end
-- Handle aiming
local pname = player:get_player_name()
if weapons.player_list[pname].aim_mode then
look_pitch = player:get_look_vertical() + (math.rad(-vert_curve) * weapon._recoil_aim_factor)
look_hori = player:get_look_horizontal() + (math.rad(hori_curve) * weapon._recoil_aim_factor)
else
look_pitch = player:get_look_vertical() + (math.rad(-vert_curve) * weapon._recoil_factor)
look_hori = player:get_look_horizontal() + (math.rad(hori_curve) * weapon._recoil_factor)
end
player:set_look_vertical(look_pitch)
player:set_look_horizontal(look_hori)
end
function raycast_minigun(player, weapon)
local wield = player:get_wielded_item():get_name()
local pname = player:get_player_name()
local ammo = weapon._ammo_type
if weapons.player_list[pname][ammo] < 101 then -- Ensure there's actually bullets in the mag/chamber
minetest.sound_play({name=weapon._firing_sound},
{pos=player:get_pos(), max_hear_distance=128, gain=1.75, pitch=math.random(95, 105)/100})
if weapon.on_fire_visual == nil then
else
weapon.on_fire_visual(player)
end
for i=1, weapon._pellets do
-- Ray calculations.
local raybegin = vector.add(player:get_pos(), {x=0, y=weapons.default_eye_height, z=0})
local raygunbegin = vector.add(player:get_pos(), {x=0, y=1.2, z=0})
local vec_x, vec_y, vec_z = 0
local _spread = solarsail.util.functions.remap(weapons.player_list[pname][ammo], 0, 100, weapon._spread, weapon._spread_max)
local _spread_aim = solarsail.util.functions.remap(weapons.player_list[pname][ammo], 0, 100, weapon._spread_aim, weapon._spread_aim_max)
-- Handle aiming
if weapons.player_list[pname].aim_mode then
vec_x = math.random(-_spread_aim * 100, _spread_aim * 100) / 100
vec_y = math.random(-_spread_aim * 100, _spread_aim * 100) / 100
vec_z = math.random(-_spread_aim * 100, _spread_aim * 100) / 100
else
vec_x = math.random(-_spread * 100, _spread * 100) / 100
vec_y = math.random(-_spread * 100, _spread * 100) / 100
vec_z = math.random(-_spread * 100, _spread * 100) / 100
end
local aim_mod = {x=vec_x, y=vec_y, z=vec_z}
local raymod = vector.add(
vector.multiply(player:get_look_dir(), weapon._range), aim_mod
)
local rayend = vector.add(raybegin, raymod)
local ray = minetest.raycast(raybegin, rayend, true, false)
local pointed = ray:next()
pointed = ray:next()
local target_pos
if weapon._tracer == nil then
else
local tracer_pos = vector.add(
vector.add(player:get_pos(), vector.new(0, 1.2, 0)),
vector.multiply(player:get_look_dir(), 1)
)
local yp = solarsail.util.functions.y_direction(player:get_look_vertical(), 20)
local px, pz = solarsail.util.functions.yaw_to_vec(player:get_look_horizontal(), 20, false)
local pv = vector.add(raybegin, {x=px, y=yp, z=pz})
local pr = vector.add(pv, raymod)
local tracer_vel = vector.add(
vector.multiply(vector.direction(pv, pr), 120),
vector.new(0, 0.44, 0)
)
local xz, y = solarsail.util.functions.get_3d_angles(
vector.add(player:get_pos(), vector.new(0, weapons.default_eye_height, 0)),
vector.add(tracer_pos, tracer_vel)
)
local ent = minetest.add_entity(tracer_pos,
"weapons:tracer_" .. weapon._tracer)
ent:set_velocity(tracer_vel)
ent:set_rotation(vector.new(y, xz, 0))
end
if pointed == nil then
else
-- Handle target;
if pointed.type == "object" then
target_pos = pointed.ref:get_pos()
else
target_pos = pointed.under
end
end
-- Calculate time to target and distance to target;
if target_pos == nil then
else
local dist = solarsail.util.functions.pos_to_dist(raybegin, target_pos)
minetest.after(dist/weapon._speed, weapon.bullet_on_hit, pointed, player,
weapon, target_pos, dist)
end
end
-- Handle recoil of the equipped weapon
apply_recoil(player, weapon, ammo)
local res = 1
weapons.player_list[pname][ammo] = weapons.player_list[pname][ammo] + res
if weapons.player_list[pname][ammo] > 100 then
weapons.player_list[pname][ammo] = 100
end
end
end
local function add_extras(player)
local ldir = player:get_look_dir()
local ppos = vector.add(player:get_pos(), vector.new(0, 1.2+ldir.y/3.5, 0))
local px, pz = solarsail.util.functions.yaw_to_vec(player:get_look_horizontal(), 1, false)
ppos = vector.add(ppos, vector.multiply(vector.new(px, 0, pz), 0.225))
local dir = vector.new(pz, 0, -px)
local res = vector.add(ppos, vector.multiply(dir, 0.25))
local ent = minetest.add_entity(res, "weapons:ar_casing")
local pvel = player:get_velocity()
pvel.x = pvel.x/2
pvel.y = pvel.y/2
pvel.z = pvel.z/2
local vel = vector.multiply(vector.new(pz/1.5, ldir.y+1, -px/1.5), 3)
vel = vector.add(vel, vector.new(math.random(-25, 25)/100, 0, math.random(-25, 25)/100))
ent:set_acceleration({x=0, y=-9.80, z=0})
ent:set_velocity(vector.add(pvel, vel))
end
local wep_rpm = 125
local shots_used = 1
weapons.register_weapon("weapons:minigun", true,
{
-- Config
_type = "gun",
_ammo_type = "minigun",
_is_energy = true,
_heat_accelerated = true,
_accel_mult = 16,
_cool_rate = 1,
_cool_timer = 0.325,
_slot = "primary",
_localisation = {
itemstring = "weapons:minigun",
name = "Minigun",
tooltip =
[[A Minigun.
Nothing saturates a target better.
Stats:
10 Damage.
Infinite Ammo!.
Unaimed spread +- 8 nodes at maximum range.
Aimed spread +- 1 nodes at maximum range.
Range 125 nodes.]],
},
-- HUD / Visual
_tracer = "ar",
_name = "minigun",
_crosshair = "shotgun_crosshair.png",
_crosshair_aim = "assault_crosshair.png",
_fov_mult = 0,
_fov_mult_aim = 0.9,
_min_arm_angle = -45,
_max_arm_angle = 75,
_arm_angle_offset = 0,
-- Sounds
_firing_sound = "ass_rifle_fire",
_reload_sound = "ass_rifle_reload",
_casing = "Armature_Casing",
-- Base Stats:
_pellets = 1,
_mag = 0,
_rpm = wep_rpm,
_reload = 6.65,
_speed = 1200,
_range = 125,
_damage = 10,
_movespeed = 0.95,
_movespeed_aim = 0.45,
_shots_used = shots_used,
_recoil = 1.5,
_recoil_vert_min = 0.2,
_recoil_vert_max = 3.5,
_recoil_hori = 0.2,
_recoil_hori_max = 5.5,
_recoil_factor = 0.8,
_recoil_aim_factor = 0.5,
_spread = 4.5,
_spread_max = 14,
_spread_aim = 0.25,
_spread_aim_max = 4.5,
_break_hits = 1,
_block_chance = 55,
-- Arm Animations + Arm visual settings;
_anim = {
idle = {x=0, y=0},
idle_fire = {x=0, y=8},
aim = {x=10, y=10},
aim_fire = {x=10, y=18},
reload = {x=60, y=219}
},
_arms = {
mesh = "assault_arms.x",
texture = "assault_rifle.png",
},
on_fire = raycast_minigun,
on_fire_visual = add_extras,
on_reload = weapons.energy_overheat,
bullet_on_hit = weapons.bullet_on_hit,
})

View File

@ -1,4 +1,4 @@
local wep_rpm = 400
local wep_rpm = 325
local shots_used = 1
local plas_ent = {
@ -19,40 +19,19 @@ local plas_ent = {
local function dmg_block(pos, weapon)
local damage, node, result =
weapons.calc_block_damage(minetest.registered_nodes[minetest.get_node(pos).name], weapon, pos)
minetest.set_node(pos, {name=node})
local p2 = minetest.get_node(pos).param2
minetest.set_node(pos, {name=node, param2=p2})
end
function plas_ent:collide(self, moveresult)
local pos = self.object:get_pos()
--[[
local pos_block
if moveresult.collisions[1] == nil then
pos_block = table.copy(self.object:get_pos())
pos_block.x = math.floor(pos_block.x)
pos_block.y = math.floor(pos_block.y)
pos_block.z = math.floor(pos_block.z)
elseif moveresult.collisions[1].type == "object" then
if moveresult.collisions[1].object:get_pos() ~= nil then
pos_block = table.copy(moveresult.collisions[1].object:get_pos())
pos_block.x = math.floor(pos_block.x)
pos_block.y = math.floor(pos_block.y)
pos_block.z = math.floor(pos_block.z)
else
pos_block = table.copy(pos)
pos_block.x = math.floor(pos_block.x)
pos_block.y = math.floor(pos_block.y)
pos_block.z = math.floor(pos_block.z)
end
elseif moveresult.collisions[1].type == "node" then
pos_block = table.copy(moveresult.collisions[1].node_pos)
else
pos_block = table.copy(pos)
pos_block.x = math.floor(pos_block.x)
pos_block.y = math.floor(pos_block.y)
pos_block.z = math.floor(pos_block.z)
dmg_block(pos_block, minetest.registered_nodes["weapons:plasma_autorifle"])
end
]]
if self._player_ref == nil then
self.object:remove()
@ -60,7 +39,6 @@ function plas_ent:collide(self, moveresult)
end
local weapon = minetest.registered_nodes["weapons:plasma_autorifle"]
--dmg_block(pos_block, weapon)
for _, player in ipairs(minetest.get_connected_players()) do
local ppos = player:get_pos()
@ -152,8 +130,9 @@ weapons.register_weapon("weapons:plasma_autorifle", true,
_ammo_type = "plasma_autorifle",
_is_energy = true,
_heat_accelerated = true,
_accel_mult = 1.75,
_accel_mult = 3.5,
_cool_rate = 0.95,
_cool_timer = 0.075,
_slot = "primary",
_localisation = {
itemstring = "weapons:plasma_autorifle",
@ -202,6 +181,8 @@ Range 150 nodes.]],
_recoil_factor = 0.8/1.5,
_recoil_aim_factor = 0.5/1.5,
_break_hits = 1,
_block_chance = 75,
_spread = 6.5,
_spread_aim = 0.5,

View File

@ -1,113 +0,0 @@
weapons.register_weapon("weapons:shotgun",
{
drawtype = "mesh",
mesh = "shotgun_fp.b3d",
range = 1,
_ammo_bg = "shotgun_bg",
_ammo_type = "primary",
_kf_name = "Shotgun",
_alt_mode = "weapons:shotgun_alt",
_fov_mult = 0,
_crosshair = "shotgun_crosshair.png",
_type = "gun",
_firing_sound = "shotgun_fire",
_casing_sound = "shotgun_casing",
_reload_sound = "shotgun_reload",
_tp_model = "shotgun_tp.x",
_name = "shotgun",
_pellets = 16,
_mag = 2,
_rpm = 225,
_reload = 3.75,
_reload_node = "weapons:shotgun_reload",
_speed = 750,
_range = 150,
_damage = 7,
_break_hits = 1,
_recoil = 14,
_spread_min = -14,
_spread_max = 14,
_tracer = "shotgun",
_phys_alt = 1,
on_fire = weapons.raycast_bullet,
bullet_on_hit = weapons.bullet_on_hit,
on_place = function(itemstack, placer, pointed_thing)
return itemstack
end,
on_drop = function(itemstack, dropper, pointed_thing)
return itemstack
end
},
{
drawtype = "mesh",
mesh = "shotgun_alt_fp.b3d",
range = 1,
_ammo_bg = "shotgun_bg",
_ammo_type = "primary",
_kf_name = "Shotgun",
_alt_mode = "weapons:shotgun",
_fov_mult = 0.925,
_crosshair = "shotgun_crosshair.png",
_type = "gun",
_firing_sound = "shotgun_fire",
_casing_sound = "shotgun_casing",
_reload_sound = "shotgun_reload",
_tp_model = "shotgun_tp.x",
_name = "shotgun",
_pellets = 16,
_mag = 2,
_rpm = 225,
_reload = 3.75,
_reload_node = "weapons:shotgun_reload",
_speed = 750,
_range = 150,
_damage = 7,
_break_hits = 1,
_recoil = 10,
_spread_min = -11,
_spread_max = 11,
_tracer = "shotgun",
_phys_alt = 0.45,
_is_alt = true,
on_fire = weapons.raycast_bullet,
bullet_on_hit = weapons.bullet_on_hit,
on_place = function(itemstack, placer, pointed_thing)
return itemstack
end,
on_drop = function(itemstack, dropper, pointed_thing)
return itemstack
end
},
{
drawtype = "mesh",
mesh = "shotgun_reload_fp.b3d",
use_texture_alpha = true,
range = 1,
_ammo_bg = "shotgun_bg",
_ammo_type = "primary",
_kf_name = "Shotgun",
_damage = 6,
_tp_model = "shotgun_tp.x",
_reset_node = "weapons:shotgun",
_mag = 2,
_fov_mult = 0,
_type = "gun",
_phys_alt = 0.7,
on_fire = weapons.raycast_bullet,
bullet_on_hit = weapons.bullet_on_hit,
on_place = function(itemstack, placer, pointed_thing)
return itemstack
end,
on_drop = function(itemstack, dropper, pointed_thing)
return itemstack
end
},
"shotgun.png", "scout_class")

View File

@ -60,8 +60,8 @@ Range 200 nodes.]],
_spread = 25,
_spread_aim = 0,
_break_hits = 2,
_block_chance = 85,
_break_hits = 4,
_block_chance = 100,
-- Arm Animations + Arm visual settings;
_anim = {