guns4d-cd2025/init.lua

228 lines
9.3 KiB
Lua

local Vec = vector
Guns4d = {
players = {},
handler_by_ObjRef = {},
gun_by_ObjRef = {} --used for getting the gun object by the ObjRef of the gun
}
--default config values, config will be added soon:tm:
Guns4d.config = {
show_mag_inv_ammo_bar = true,
show_mag_inv_ammo_count = true,
show_gun_inv_ammo_count = true,
control_hybrid_toggle_threshold = .3,
control_held_toggle_threshold = 0,
empty_symbol = "E",
default_damage_group = "fleshy",
infinite_ammo_priv = "guns4d_infinite_ammo",
interpret_initial_wear_as_ammo = false,
punch_from_player_not_gun = true,
vertical_rotation_factor = 10,
simple_headshot = true, --holdover feature before a more complex system is implemented
simple_headshot_body_ratio = .75, --percentage of hitbox height that is body.
default_fov = 80,
headshot_damage_factor = 1.75,
enable_touchscreen_command_name = "guns4d_enable_touchmode",
minimum_supersonic_energy_assumption = 900, --used to determine the energy of a "supersonic" bullet for bullet whizzing sound effects
default_audio_attenuation_rate = .8, --changes the dropoff rate of sound. Acts as a multiplier for the distance used to calculate inverse square law. Most guns (from the gun packs) set their own, so this is mainly for reloads.
mix_supersonic_and_subsonic_sounds = true,
default_pass_sound_mixing_factor = 10,
third_person_gain_multiplier = 1/3,
default_penetration_iteration_distance = .25,
maximum_bullet_holes = 20,
--enable_assert = false,
realistic_items = false
--`["official_content.replace_ads_with_bloom"] = false,
--`["official_content.uses_magazines"] = true
}
local modpath = minetest.get_modpath("guns4d")
local conf = Settings(modpath.."/guns4d_settings.conf"):to_table() or {}
local mt_conf = minetest.settings:to_table() --allow use of MT config for servers that regularly update 4dguns through it's development
for i, v in pairs(Guns4d.config) do
--Guns4d.config[i] = conf[i] or minetest.settings["guns4d."..i] or Guns4d.config[i]
--cant use or because it'd evaluate to false if the setting is alse
if mt_conf["guns4d."..i] ~= nil then
Guns4d.config[i] = mt_conf["guns4d."..i]
elseif conf[i] ~= nil then
Guns4d.config[i] = conf[i]
end
end
minetest.rmdir(modpath.."/temp", true)
minetest.mkdir(modpath.."/temp")
dofile(modpath.."/infinite_ammo.lua")
dofile(modpath.."/misc_helpers.lua")
dofile(modpath.."/item_entities.lua")
dofile(modpath.."/play_sound.lua")
dofile(modpath.."/visual_effects.lua")
dofile(modpath.."/default_controls.lua")
dofile(modpath.."/touch_support.lua")
dofile(modpath.."/block_values.lua")
dofile(modpath.."/ammo_api.lua")
local path = modpath .. "/classes"
dofile(path.."/Bullet_hole.lua")
dofile(path.."/Bullet_ray.lua")
dofile(path.."/Control_handler.lua")
dofile(path.."/Ammo_handler.lua")
dofile(path.."/Sprite_scope.lua")
dofile(path.."/Dynamic_crosshair.lua")
dofile(path.."/Gun.lua") --> loads /classes/gun_construct.lua
dofile(path.."/Player_model_handler.lua")
dofile(path.."/Player_handler.lua")
--model compatibility
path = modpath .. "/models"
dofile(path.."/3darmor/init.lua")
--load after
path = minetest.get_modpath("guns4d")
local player_handler = Guns4d.player_handler
local objref_mtable
minetest.register_on_joinplayer(function(player)
local pname = player:get_player_name()
Guns4d.players[pname] = player_handler:new({player=player}) --player handler does just what it sounds like- see classes/Player_handler
Guns4d.handler_by_ObjRef[player] = Guns4d.players[pname]
--set the FOV to a predictable value
player:set_fov(Guns4d.config.default_fov)
--ObjRef overrides will be integrated into MTUL (eventually TM)
if not objref_mtable then
objref_mtable = getmetatable(player)
local old_set_fov = objref_mtable.set_fov
Guns4d.old_set_fov = old_set_fov
function objref_mtable.set_fov(self, ...)
local handler = Guns4d.handler_by_ObjRef[self]
local fov = select(1, ...)
if handler then --check, just in case it's not a player (and thus should throw an error)
if fov == 0 then
fov = Guns4d.config.default_fov
elseif select(2, ...) == true then
fov = Guns4d.config.default_fov*fov
end
handler.default_fov = fov
if handler.fov_lock then return end
end
local args = {...}
args[1] = fov --basically permenantly set the player's fov to 80, making multipliers and resets return there.
old_set_fov(self, unpack(args))
end
local old_get_pos = objref_mtable.get_pos
function objref_mtable.get_pos(self, ...)
local gun = Guns4d.gun_by_ObjRef[self]
local mt_pos = old_get_pos(self, ...)
if mt_pos then --mods (including this) will frequently use this as a check if an ent is still around.
if (not gun) or gun.released then
return mt_pos
else
local v, _, _ = gun:get_pos()
return v
end
end
end
function objref_mtable._guns4d_old_get_pos(self, ...)
return old_get_pos(self, ...)
end
local old_set_animation = objref_mtable.set_animation
--put vargs there for maintainability.
function objref_mtable.set_animation(self, frame_range, frame_speed, frame_blend, frame_loop, ...)
local gun = Guns4d.gun_by_ObjRef[self]
if gun then
local data = gun.animation_data
data.runtime = 0
data.fps = frame_speed or 15
data.loop = frame_loop
if frame_loop == nil then --still have no idea what nutjob made the default true >:(
frame_loop = false
end
--so... minetest is stupid, and so it won't let me set something to the same animation twice (utterly fucking brilliant).
--This means I literally need to flip flop between +1 frames
frame_range = table.copy(frame_range)
--minetest.chat_send_all(dump(frame_range))
if (data.frames.x == frame_range.x and data.frames.y == frame_range.y) and not (frame_range.x==frame_range.y) then
--oh yeah, and it only accepts whole frames... because of course.
frame_range.x = frame_range.x+1
--minetest.chat_send_all("+1")
end
--frame_blend = 25
--minetest.chat_send_all(dump(frame_range))
data.frames = frame_range
data.current_frame = data.frames.x
end
return old_set_animation(self, frame_range, frame_speed, frame_blend, frame_loop, ...)
end
local old_set_frame_speed = objref_mtable.set_animation_frame_speed
function objref_mtable.set_animation_frame_speed(self, frame_speed, ...)
local gun = Guns4d.gun_by_ObjRef[self]
if gun then
gun.animation_data.fps = frame_speed or 15
end
old_set_frame_speed(self, frame_speed, ...)
end
local old_remove = objref_mtable.remove
function objref_mtable.remove(self)
local gun = Guns4d.gun_by_ObjRef[self]
if gun then
Guns4d.gun_by_ObjRef[self] = nil
end
return old_remove(self)
end
--[[minetest.after(1, function(playername)
minetest.get_player_by_name(playername):hud_add({
hud_elem_type = "compass",
text = "gun_mrkr.png",
scale = {x=1, y=1},
alignment = {x=0,y=0},
position = {x=.5,y=.5},
size = {x=200, y=200},
offset = {x=-.5,y=.5},
direction = 0
})
end, player:get_player_name())]]
end
end)
--we grab the ObjRef metatable from the first available source.
--because we want guns to function as real objects, we have to override the metatable get_pos() for all objects
--this is made more efficient by using a table lookup for ObjRefs we want to update properly.
--"uns4d[ObjRef] = gun" is declared on_activate() in the entity.
--[[minetest.after(0, function()
end)]]
minetest.register_on_leaveplayer(function(player)
local pname = player:get_player_name()
Guns4d.players[pname]:prepare_deletion()
Guns4d.players[pname] = nil
Guns4d.handler_by_ObjRef[player] = nil
end)
--ticks are rarely used, but still ideal for rare checks with minimal overhead.
TICK = 0
minetest.register_globalstep(function(dt)
TICK = TICK + 1
if TICK > 100000 then TICK = 0 end
for player, handler in pairs(Guns4d.players) do
if not handler then
--spawn the player handler. The player handler handles the gun(s),
--the player's model, and controls
handler = player_handler:new({player=player})
end
handler:update(dt)
--[[minetest.get_player_by_name(player):hud_add({
hud_elem_type = "compass",
text = "gay.png",
scale = {x=10, y=10},
alignment = {x=0,y=0},
offset = {x=-.5,y=-.5},
direction = 0
})]]
end
end)