--- a default control system for aiming, reloading, firing, reloading, and more. Guns4d.default_controls = { controls = {} } Guns4d.default_controls.aim = { conditions = {"RMB"}, loop = false, timer = 0, func = function(active, interrupted, data, busy_list, gun, handler) if active then handler.control_handler.ads = not handler.control_handler.ads end end } Guns4d.default_controls.auto = { conditions = {"LMB"}, loop = true, timer = 0, func = function(active, interrupted, data, busy_list, gun, handler) if gun.properties.firemodes[gun.current_firemode] == "auto" then gun:attempt_fire() end end } Guns4d.default_controls.firemode = { conditions = {"sneak", "zoom"}, loop = false, timer = 0, func = function(active, interrupted, data, busy_list, gun, handler) if active then if not (busy_list.on_use or busy_list.auto) then gun:cycle_firemodes() end end end } --[[Guns4d.default_controls.toggle_safety = { conditions = {"sneak", "zoom"}, loop = false, timer = 2, func = function(active, interrupted, data, busy_list, gun, handler) local safety = "a real variable here" if safety and not data.timer_set then end if not (busy_list.on_use or busy_list.auto) then end end }]] Guns4d.default_controls.on_use = function(itemstack, handler, pointed_thing, busy_list) local gun = handler.gun local fmode = gun.properties.firemodes[gun.current_firemode] if fmode ~= "safe" and not (gun.burst_queue > 0) then local fired = gun:attempt_fire() if (fmode == "burst") then gun.burst_queue = gun.properties.burst-((fired and 1) or 0) end end --handler.control_handler.busy_list.on_use = true end local reload_actions = {} function Guns4d.default_controls.register_reloading_state_type(name, def) assert(type(def)=="table", "improper definition type") assert(type(def.on_completion)=="function", "action has no completion function") --return a bool (or nil) indicating wether to progress. Nil returns the function (breaking out of the reload cycle.) assert(type(def.validation_check)=="function") --return bool indicating wether it is valid. If nil it is assumed to be valid reload_actions[name] = def end local reg_mstate = Guns4d.default_controls.register_reloading_state_type reg_mstate("unload_mag", { on_completion = function(gun, ammo_handler, next_state) --what happens when the timer is completed. if next_state and next_state.action == "store" then ammo_handler:set_unloading(true) --if interrupted it will drop to ground, so just make it appear as if the gun is already unloaded in hotbar else ammo_handler:unload_magazine(true) --unload to ground if it's not going to be stored next state end return true --true indicates to move to the next action. If false it would replay the same state, if nil it would break out of the function and not continue until reset entirely. end, validation_check = function(gun, ammo_handler, next_state) if ammo_handler.ammo.loaded_mag == "empty" then return false --indicates that the state is not valid, this moves to the next state. If true then it is valid and it will start the reload action. Nil breaks out entirely. end return true end }) reg_mstate("store", { on_completion = function(gun, ammo_handler, next_state) --[[local pause = false --needs to happen before so we don't detect the ammo we just unloaded if not ammo_handler:inventory_has_ammo() then pause=true end]] if gun.properties.ammo.magazine_only and (ammo_handler.ammo.loaded_mag ~= "empty") then ammo_handler:unload_magazine() else ammo_handler:unload_all() end --if there's no ammo make hold so you don't reload the same ammo you just unloaded. --[[if pause then return end return true]] end, validation_check = function(gun, ammo_handler, next_state) if gun.properties.ammo.magazine_only and (ammo_handler.ammo.loaded_mag == "empty") then return false end return true end, interrupt = function(gun, ammo_handler) if gun.properties.ammo.magazine_only and (ammo_handler.ammo.loaded_mag ~= "empty") then ammo_handler:unload_magazine(true) --"true" is for to_ground else ammo_handler:unload_all(true) end end }) reg_mstate("load", { on_completion = function(gun, ammo_handler, next_state) if gun.properties.ammo.magazine_only then ammo_handler:load_magazine() else ammo_handler:load_flat() end if (not next_state) or (next_state.action ~= "charge") then --chamber the round automatically. ammo_handler:chamber_round() end return true end, validation_check = function(gun, ammo_handler, next_state) if gun.properties.ammo.magazine_only then if not ammo_handler:can_load_magazine() then return false end else if not ammo_handler:can_load_flat() then return false end end return true end }) reg_mstate("load_cartridge_once", { on_completion = function(gun, ammo_handler, next_state) ammo_handler:load_single_cartridge() --load one time, always continue return true end, validation_check = function(gun, ammo_handler, next_state) if (ammo_handler.ammo.total_bullets