From 795a0d6f6b4c21e4003f6893a823fb7f2586ea53 Mon Sep 17 00:00:00 2001 From: Jordan Snelling Date: Sat, 6 Feb 2021 02:44:45 +0000 Subject: [PATCH] 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. --- .gitignore | 10 +- minetest.conf | 12 +- mods/persistence/db/readme.txt | 1 + mods/persistence/db/weapons_player_data.prs | 1 - mods/solarsail/init.lua | 115 ++++---- mods/weapons/auth.lua | 106 ++++++++ mods/weapons/controls.lua | 6 +- mods/weapons/functions.lua | 66 +++++ mods/weapons/hud.lua | 3 +- mods/weapons/init.lua | 45 +++- mods/weapons/player.lua | 2 + mods/weapons/weapons.lua | 4 +- mods/weapons/weapons/assault_rifle.lua | 2 +- mods/weapons/weapons/burst_rifle.lua | 2 +- mods/weapons/weapons/light_machine_gun.lua | 101 +++++++ mods/weapons/weapons/minigun.lua | 254 ++++++++++++++++++ mods/weapons/weapons/plasma_autorifle.lua | 37 +-- mods/weapons/weapons/shotgun.lua | 113 -------- mods/weapons/weapons/sniper_rifle.lua | 4 +- .../{scout_rifle.lua => veteran_rifle.lua} | 0 20 files changed, 679 insertions(+), 205 deletions(-) create mode 100644 mods/persistence/db/readme.txt delete mode 100644 mods/persistence/db/weapons_player_data.prs create mode 100644 mods/weapons/auth.lua create mode 100644 mods/weapons/weapons/light_machine_gun.lua create mode 100644 mods/weapons/weapons/minigun.lua delete mode 100644 mods/weapons/weapons/shotgun.lua rename mods/weapons/weapons/{scout_rifle.lua => veteran_rifle.lua} (100%) diff --git a/.gitignore b/.gitignore index 5c35332..c765264 100644 --- a/.gitignore +++ b/.gitignore @@ -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 \ No newline at end of file +.vs diff --git a/minetest.conf b/minetest.conf index 5aa8322..e4882c1 100644 --- a/minetest.conf +++ b/minetest.conf @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/mods/persistence/db/readme.txt b/mods/persistence/db/readme.txt new file mode 100644 index 0000000..45a6484 --- /dev/null +++ b/mods/persistence/db/readme.txt @@ -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. \ No newline at end of file diff --git a/mods/persistence/db/weapons_player_data.prs b/mods/persistence/db/weapons_player_data.prs deleted file mode 100644 index 8c7d0d7..0000000 --- a/mods/persistence/db/weapons_player_data.prs +++ /dev/null @@ -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"}} \ No newline at end of file diff --git a/mods/solarsail/init.lua b/mods/solarsail/init.lua index 023e5bf..bfd9763 100644 --- a/mods/solarsail/init.lua +++ b/mods/solarsail/init.lua @@ -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") \ No newline at end of file diff --git a/mods/weapons/auth.lua b/mods/weapons/auth.lua new file mode 100644 index 0000000..912ced0 --- /dev/null +++ b/mods/weapons/auth.lua @@ -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, +}) \ No newline at end of file diff --git a/mods/weapons/controls.lua b/mods/weapons/controls.lua index a65d9d4..dc926b7 100644 --- a/mods/weapons/controls.lua +++ b/mods/weapons/controls.lua @@ -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 diff --git a/mods/weapons/functions.lua b/mods/weapons/functions.lua index c08a270..46d6207 100644 --- a/mods/weapons/functions.lua +++ b/mods/weapons/functions.lua @@ -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 diff --git a/mods/weapons/hud.lua b/mods/weapons/hud.lua index 20cc940..930707d 100644 --- a/mods/weapons/hud.lua +++ b/mods/weapons/hud.lua @@ -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 diff --git a/mods/weapons/init.lua b/mods/weapons/init.lua index 34de12c..3d188fd 100644 --- a/mods/weapons/init.lua +++ b/mods/weapons/init.lua @@ -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") diff --git a/mods/weapons/player.lua b/mods/weapons/player.lua index d51030f..8257e78 100644 --- a/mods/weapons/player.lua +++ b/mods/weapons/player.lua @@ -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" } diff --git a/mods/weapons/weapons.lua b/mods/weapons/weapons.lua index 69cb57f..da42662 100644 --- a/mods/weapons/weapons.lua +++ b/mods/weapons/weapons.lua @@ -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 diff --git a/mods/weapons/weapons/assault_rifle.lua b/mods/weapons/weapons/assault_rifle.lua index 12b76cb..ff840da 100644 --- a/mods/weapons/weapons/assault_rifle.lua +++ b/mods/weapons/weapons/assault_rifle.lua @@ -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 = { diff --git a/mods/weapons/weapons/burst_rifle.lua b/mods/weapons/weapons/burst_rifle.lua index d8fe449..b2d04ac 100644 --- a/mods/weapons/weapons/burst_rifle.lua +++ b/mods/weapons/weapons/burst_rifle.lua @@ -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 = { diff --git a/mods/weapons/weapons/light_machine_gun.lua b/mods/weapons/weapons/light_machine_gun.lua new file mode 100644 index 0000000..9df068b --- /dev/null +++ b/mods/weapons/weapons/light_machine_gun.lua @@ -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, +}) \ No newline at end of file diff --git a/mods/weapons/weapons/minigun.lua b/mods/weapons/weapons/minigun.lua new file mode 100644 index 0000000..7d55d67 --- /dev/null +++ b/mods/weapons/weapons/minigun.lua @@ -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, +}) \ No newline at end of file diff --git a/mods/weapons/weapons/plasma_autorifle.lua b/mods/weapons/weapons/plasma_autorifle.lua index 309e0fa..f109bc9 100644 --- a/mods/weapons/weapons/plasma_autorifle.lua +++ b/mods/weapons/weapons/plasma_autorifle.lua @@ -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, diff --git a/mods/weapons/weapons/shotgun.lua b/mods/weapons/weapons/shotgun.lua deleted file mode 100644 index f80fa20..0000000 --- a/mods/weapons/weapons/shotgun.lua +++ /dev/null @@ -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") \ No newline at end of file diff --git a/mods/weapons/weapons/sniper_rifle.lua b/mods/weapons/weapons/sniper_rifle.lua index a5f74a5..5674155 100644 --- a/mods/weapons/weapons/sniper_rifle.lua +++ b/mods/weapons/weapons/sniper_rifle.lua @@ -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 = { diff --git a/mods/weapons/weapons/scout_rifle.lua b/mods/weapons/weapons/veteran_rifle.lua similarity index 100% rename from mods/weapons/weapons/scout_rifle.lua rename to mods/weapons/weapons/veteran_rifle.lua