diff --git a/classes/Gun_ammo.lua b/classes/Ammo_handler.lua similarity index 97% rename from classes/Gun_ammo.lua rename to classes/Ammo_handler.lua index daa9e1d..7d04378 100644 --- a/classes/Gun_ammo.lua +++ b/classes/Ammo_handler.lua @@ -1,4 +1,4 @@ -Gun_ammo = Instantiatable_class:inherit({ +Ammo_handler = Instantiatable_class:inherit({ name = "Gun_ammo_handler", construct = function(def) assert(def.gun) diff --git a/classes/Gun.lua b/classes/Gun.lua index 61b0cb3..5006375 100644 --- a/classes/Gun.lua +++ b/classes/Gun.lua @@ -298,7 +298,6 @@ function gun_default:update_wag(dt) end end end - function gun_default:update_recoil(dt) for axis, _ in pairs(self.offsets.recoil) do for _, i in pairs({"x","y"}) do diff --git a/docs/required_features.txt b/docs/required_features.txt index e701997..8c5b2b7 100644 --- a/docs/required_features.txt +++ b/docs/required_features.txt @@ -39,4 +39,5 @@ auxillary (beta+/never) bullet drop (maybe bullet wind?) bullet tracers inverse kinematics - stamina \ No newline at end of file + stamina + a better system for reloading magazine (something like a inventory that fractionally reloads magazines so it takes time.) \ No newline at end of file diff --git a/init.lua b/init.lua index ce23537..8de5678 100644 --- a/init.lua +++ b/init.lua @@ -7,6 +7,7 @@ dofile(path.."/misc_helpers.lua") dofile(path.."/visual_effects.lua") dofile(path.."/gun_api.lua") dofile(path.."/block_values.lua") +dofile(path.."/register_ammo.lua") path = path .. "/classes" dofile(path.."/Instantiatable_class.lua") dofile(path.."/Bullet_ray.lua") diff --git a/register_ammo.lua b/register_ammo.lua index c23c36e..3f74417 100644 --- a/register_ammo.lua +++ b/register_ammo.lua @@ -5,13 +5,10 @@ Default_bullet = { force_mmRHA = 1, dropoff_mmRHA = 0, damage = 0, - itemstring = "", - construct = function(def) - assert(not def.instance, "attempt to create instance of a template") - assert(rawget(def, "itemstring"), "no string provided to new bullet template") - assert(minetest.registered_items[def.itemstring], "bullet item is not registered. Check dependencies?") - - end +} +Default_mag = { + capacity = 1, + craft_reload = true } Guns4d.ammo = { registered_bullets = { @@ -21,26 +18,144 @@ Guns4d.ammo = { } } +local max_wear = 65535 function Guns4d.ammo.register_bullet(def) assert(def.itemstring) assert(minetest.registered_items[def.itemstring], "no item '"..def.itemstring.."' found. Must be a registered item (check dependencies?)") Guns4d.ammo.registered_bullets[def.itemstring] = table.fill(Default_bullet, def) end -function Guns4d.ammo.register_magazine(def) - assert(def.accepted_bullets, "missing property def.accepted_bullets. Need specified bullets to allow for loading") - for i, v in pairs(def.accepted_bullets) do - if not Guns4d.ammo.registered_bullets[v] then print("WARNING! bullet "..v.." not registered! is this a mistake?") end +function Guns4d.ammo.initialize_mag_data(itemstack, meta) + meta = meta or itemstack:get_meta() + if meta:get_string("guns4d_loaded_bullets") == "" then + meta:set_string("guns4d_loaded_bullets", minetest.serialize({})) + itemstack:set_wear(max_wear) end + return itemstack +end +function Guns4d.ammo.update_mag_wear(def, itemstack, meta) + meta = meta or itemstack:get_meta() + local bullets = minetest.deserialize(meta:get_string("guns4d_loaded_bullets")) + local count = 0 + for i, v in pairs(bullets) do + count = count + v + end + itemstack:set_wear(max_wear-(max_wear*count/def.capacity)) + return itemstack +end +function Guns4d.ammo.register_magazine(def) + def = table.fill(Default_mag, def) + assert(def.accepted_bullets, "missing property def.accepted_bullets. Need specified bullets to allow for loading") + assert(def.itemstring, "missing item name") + def.accepted_bullets_set = {} --this table is a "lookup" table, I didn't go to college so I have no idea + for i, v in pairs(def.accepted_bullets) do + if not Guns4d.ammo.registered_bullets[v] then print("guns4D: WARNING! bullet "..v.." not registered! is this a mistake?") end + def.accepted_bullets_set[v] = true + end + Guns4d.ammo.registered_magazines[def.itemstring] = def --register craft prediction - minetest.register_craft_predict(function(itemstack, player, old_craft_grid, craft_inv) - if craft_inv:contains_item("craft", def.itemstring) and itemstack:get_name()=="" then - --potentially give predicted ammo gauge here - return def.itemstring + local old_on_use = minetest.registered_items[def.itemstring].on_use + minetest.override_item(def.itemstring, { + on_use = function(itemstack, user, pointed_thing) + if old_on_use then + old_on_use(itemstack, user, pointed_thing) + end + local meta = itemstack:get_meta() + local ammo = minetest.deserialize(meta:get_string("guns4d_loaded_bullets")) + if ammo then + minetest.chat_send_player(user:get_player_name(), "rounds in magazine:") + for i, v in pairs(ammo) do + minetest.chat_send_player(user:get_player_name(), " "..i.." : "..tostring(v)) + end + else + minetest.chat_send_player(user:get_player_name(), "magazine is empty") + end end - end) - minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) - if craft_inv:contains_item("craft", def.itemstring) and craft_inv:contains_item("craftpreview", def.itemstring) then - end - end) + }) + if def.craft_reload then + minetest.register_craft_predict(function(itemstack, player, old_craft_grid, craft_inv) + --initialize all mags + local num_mags = 0 + for i, v in pairs(craft_inv:get_list("craft")) do + if v:get_name() == def.itemstring then + num_mags = num_mags + 1 + Guns4d.ammo.initialize_mag_data(v) + end + end + print(num_mags) + if itemstack:get_name()=="" then + for i, v in pairs(craft_inv:get_list("craft")) do + local name =v:get_name() + if name == def.itemstring then + craft_inv:set_stack("craft", i, Guns4d.ammo.initialize_mag_data(v)) + end + if (name~=def.itemstring) and Guns4d.ammo.registered_magazines[name] then + return + end + if (name~="") and (not (name == def.itemstring)) and (not def.accepted_bullets_set[name]) then + print("name:", dump(def.accepted_bullets_set)) + return + end + end + return def.itemstring + end + end) + minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) + if craft_inv:contains_item("craft", def.itemstring) and craft_inv:contains_item("craftpreview", def.itemstring) then + local mag_stack_index + local craft_list = craft_inv:get_list("craft") + --there's basically no way to cleanly avoid two iterations, annoyingly. + for i, v in pairs(craft_list) do + local name = v:get_name() + if (name~=def.itemstring) then + if Guns4d.ammo.registered_magazines[name] then + return + end + else + mag_stack_index = i + end + if not def.accepted_bullets_set[name] then + if (name ~= "") and (name~=def.itemstring) then + print("return", "'"..name.."'") + return + end + end + end + local bullets_unfilled = def.capacity + local mag_stack = craft_inv:get_stack("craft", mag_stack_index) + local new_ammo_table = minetest.deserialize(mag_stack:get_meta():get_string("guns4d_loaded_bullets")) + for i, v in pairs(new_ammo_table) do + bullets_unfilled = bullets_unfilled - v + end + local new_stack = ItemStack(def.itemstring) + for i, v in pairs(craft_list) do + local name = v:get_name() + if def.accepted_bullets_set[name] then + local bullet_stack_count = v:get_count() + --check if there's not enough bullets to fill it + if bullet_stack_count <= bullets_unfilled then + --if not then remove the stack and add it + bullets_unfilled = bullets_unfilled - bullet_stack_count + new_ammo_table[name] = (new_ammo_table[name] or 0)+bullet_stack_count + craft_inv:set_stack("craft", i, "") + else + --if there is then add the bullets needed to it's index in the table + --and subtract. + new_ammo_table[name] = (new_ammo_table[name] or 0)+bullets_unfilled + v:set_count(bullet_stack_count-bullets_unfilled) + craft_inv:set_stack("craft", i, v) + bullets_unfilled = 0 + end + end + end + mag_stack:set_count(mag_stack:get_count()-1) + craft_inv:set_stack("craft", mag_stack_index, mag_stack) + new_stack:get_meta():set_string("guns4d_loaded_bullets", minetest.serialize(new_ammo_table)) + new_stack = Guns4d.ammo.update_mag_wear(def, new_stack) + --print(new_stack:get_string()) + return new_stack + end + end) + end --register the actual recipe to add ammo to a mag end +