signfifficantly changed class & structure system, began work on ammo systems
This commit is contained in:
parent
00ea0ff13e
commit
a71c84a524
140
classes/Gun.lua
140
classes/Gun.lua
@ -1,9 +1,10 @@
|
||||
local Vec = vector
|
||||
local gun = {
|
||||
local gun_default = {
|
||||
--itemstack = Itemstack
|
||||
--gun_entity = ObjRef
|
||||
name = "__template__",
|
||||
registered = {},
|
||||
property_modifiers = {},
|
||||
properties = {
|
||||
hip = {
|
||||
offset = Vec.new(),
|
||||
@ -55,12 +56,11 @@ local gun = {
|
||||
flash_offset = Vec.new(),
|
||||
aim_time = 1,
|
||||
firerateRPM = 10000,
|
||||
controls = {}
|
||||
controls = {},
|
||||
accepted_mags = {}
|
||||
},
|
||||
offsets = {
|
||||
pos = Vec.new(),
|
||||
player_rotation = Vec.new(),
|
||||
dir = Vec.new(),
|
||||
--I'll need all three of them, do some precalculation.
|
||||
total_offset_rotation = {
|
||||
gun_axial = Vec.new(),
|
||||
@ -93,9 +93,6 @@ local gun = {
|
||||
player_axial = Vec.new(),
|
||||
},
|
||||
},
|
||||
particle_spawners = {
|
||||
--muzzle_smoke
|
||||
},
|
||||
--magic number BEGONE
|
||||
consts = {
|
||||
HIP_PLAYER_GUN_ROT_RATIO = .75,
|
||||
@ -106,7 +103,9 @@ local gun = {
|
||||
HAS_BREATHING = true,
|
||||
HAS_SWAY = true,
|
||||
HAS_WAG = true,
|
||||
INFINITE_AMMO_IN_CREATIVE = true,
|
||||
},
|
||||
particle_spawners = {},
|
||||
walking_tick = 0,
|
||||
time_since_last_fire = 0,
|
||||
time_since_creation = 0,
|
||||
@ -114,7 +113,9 @@ local gun = {
|
||||
muzzle_flash = Guns4d.muzzle_flash
|
||||
}
|
||||
|
||||
function gun:fire()
|
||||
function gun_default:spend_round()
|
||||
end
|
||||
function gun_default:fire()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
if self.rechamber_time <= 0 then
|
||||
local dir = self.dir
|
||||
@ -138,7 +139,7 @@ function gun:fire()
|
||||
end
|
||||
end
|
||||
|
||||
function gun:recoil()
|
||||
function gun_default:recoil()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
for axis, recoil in pairs(self.velocities.recoil) do
|
||||
for _, i in pairs({"x","y"}) do
|
||||
@ -148,7 +149,7 @@ function gun:recoil()
|
||||
self.time_since_last_fire = 0
|
||||
end
|
||||
|
||||
function gun:get_dir(rltv)
|
||||
function gun_default:get_dir(rltv)
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
local player = self.player
|
||||
local player_rotation
|
||||
@ -161,24 +162,11 @@ function gun:get_dir(rltv)
|
||||
local dir = Vec.new(Vec.rotate({x=0, y=0, z=1}, {y=0, x=((rotation.gun_axial.x+rotation.player_axial.x+player_rotation.x)*math.pi/180), z=0}))
|
||||
dir = Vec.rotate(dir, {y=((rotation.gun_axial.y+rotation.player_axial.y+player_rotation.y)*math.pi/180), x=0, z=0})
|
||||
local hud_pos = dir+player:get_pos()+{x=0,y=player:get_properties().eye_height,z=0}+vector.rotate(player:get_eye_offset()/10, {x=0,y=player_rotation.y*math.pi/180,z=0})
|
||||
if not false then
|
||||
local hud = player:hud_add({
|
||||
hud_elem_type = "image_waypoint",
|
||||
text = "muzzle_flash2.png",
|
||||
world_pos = hud_pos,
|
||||
scale = {x=10, y=10},
|
||||
alignment = {x=0,y=0},
|
||||
offset = {x=0,y=0},
|
||||
})
|
||||
minetest.after(0, function(hud)
|
||||
player:hud_remove(hud)
|
||||
end, hud)
|
||||
end
|
||||
return dir
|
||||
end
|
||||
|
||||
|
||||
function gun:get_pos(added_pos)
|
||||
function gun_default:get_pos(added_pos)
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
added_pos = Vec.new(added_pos)
|
||||
local player = self.player
|
||||
@ -217,7 +205,7 @@ function gun:get_pos(added_pos)
|
||||
return bone_pos+gun_offset+handler:get_pos(), bone_pos, gun_offset
|
||||
end
|
||||
|
||||
function gun:add_entity()
|
||||
function gun_default:add_entity()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
self.entity = minetest.add_entity(self.player:get_pos(), self.name.."_visual")
|
||||
local obj = self.entity:get_luaentity()
|
||||
@ -225,7 +213,7 @@ function gun:add_entity()
|
||||
obj:on_step()
|
||||
end
|
||||
|
||||
function gun:has_entity()
|
||||
function gun_default:has_entity()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
if not self.entity then return false end
|
||||
if not self.entity:get_pos() then return false end
|
||||
@ -233,7 +221,7 @@ function gun:has_entity()
|
||||
end
|
||||
|
||||
--update the gun, da meat and da potatoes
|
||||
function gun:update(dt)
|
||||
function gun_default:update(dt)
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
if not self:has_entity() then self:add_entity() end
|
||||
self.pos = self:get_pos()
|
||||
@ -269,11 +257,6 @@ function gun:update(dt)
|
||||
|
||||
--sprite scope
|
||||
if self.properties.sprite_scope then
|
||||
if not self.sprite_scope then
|
||||
self.sprite_scope = self.properties.sprite_scope:new({
|
||||
gun = self
|
||||
})
|
||||
end
|
||||
self.sprite_scope:update()
|
||||
end
|
||||
|
||||
@ -282,7 +265,8 @@ function gun:update(dt)
|
||||
total_rot.player_axial = offsets.recoil.player_axial + offsets.walking.player_axial + offsets.sway.player_axial + {x=offsets.breathing.player_axial,y=0,z=0} + {x=0,y=0,z=0}
|
||||
total_rot.gun_axial = offsets.recoil.gun_axial + offsets.walking.gun_axial + offsets.sway.gun_axial
|
||||
end
|
||||
function gun:update_wag(dt)
|
||||
|
||||
function gun_default:update_wag(dt)
|
||||
local handler = self.handler
|
||||
if handler.walking then
|
||||
self.walking_tick = self.walking_tick + (dt*Vec.length(self.player:get_velocity()))
|
||||
@ -314,7 +298,8 @@ function gun:update_wag(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
function gun:update_recoil(dt)
|
||||
|
||||
function gun_default:update_recoil(dt)
|
||||
for axis, _ in pairs(self.offsets.recoil) do
|
||||
for _, i in pairs({"x","y"}) do
|
||||
local recoil = self.offsets.recoil[axis][i]
|
||||
@ -351,7 +336,8 @@ function gun:update_recoil(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
function gun:update_breathing(dt)
|
||||
|
||||
function gun_default:update_breathing(dt)
|
||||
local breathing_info = {pause=1.4, rate=4.2}
|
||||
--we want X to be between 0 and 4.2. Since math.pi is a positive crest, we want X to be above it before it reaches our-
|
||||
--"length" (aka rate-pause), thus it will pi/length or pi/(rate-pause) will represent out slope of our control.
|
||||
@ -364,7 +350,8 @@ function gun:update_breathing(dt)
|
||||
self.offsets.breathing.player_axial = scale*(math.sin(x))
|
||||
end
|
||||
end
|
||||
function gun:update_sway(dt)
|
||||
|
||||
function gun_default:update_sway(dt)
|
||||
for axis, sway in pairs(self.offsets.sway) do
|
||||
local sway_vel = self.velocities.sway[axis]
|
||||
local ran
|
||||
@ -384,18 +371,25 @@ function gun:update_sway(dt)
|
||||
self.velocities.sway[axis] = sway_vel
|
||||
end
|
||||
end
|
||||
function gun:prepare_deletion()
|
||||
|
||||
function gun_default:prepare_deletion()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
if self:has_entity() then self.entity:remove() end
|
||||
if self.sprite_scope then self.sprite_scope:prepare_deletion() end
|
||||
end
|
||||
--construction for the gun class
|
||||
gun.construct = function(def)
|
||||
--construction for the base gun class
|
||||
gun_default.construct = function(def)
|
||||
if def.instance then
|
||||
--remember to give gun an id
|
||||
assert(def.itemstack, "no itemstack provided for initialized object")
|
||||
assert(def.player, "no player provided")
|
||||
--make some quick checks.
|
||||
assert(def.handler, "no player handler object provided")
|
||||
|
||||
--initialize some variables
|
||||
def.player = def.handler.player
|
||||
local meta = def.itemstack:get_meta()
|
||||
def.meta = meta
|
||||
local out = {}
|
||||
|
||||
--create ID so we can track switches between weapons
|
||||
if meta:get_string("guns4d_id") == "" then
|
||||
local id = tostring(Unique_id.generate())
|
||||
meta:set_string("guns4d_id", id)
|
||||
@ -404,30 +398,55 @@ gun.construct = function(def)
|
||||
else
|
||||
def.id = meta:get_string("guns4d_id")
|
||||
end
|
||||
--make sure there's nothing missing, aka copy over all of the properties.
|
||||
def.properties = table.fill(gun.properties, def.properties)
|
||||
--so, we copy the offsets table so we have all of the offsets
|
||||
--then we create new vectors for gun_axial and player_axial.
|
||||
def.offsets = table.deep_copy(gun.offsets)
|
||||
for i, tbl in pairs(def.offsets) do
|
||||
if tbl.gun_axial and tbl.player_axial and (not i=="breathing") then
|
||||
tbl.gun_axial = Vec.new(tbl.gun_axial)
|
||||
tbl.player_axial = Vec.new(tbl.player_axial)
|
||||
|
||||
--unavoidable table instancing
|
||||
def.properties = table.fill(def.base_class.properties, def.properties)
|
||||
def.particle_spawners = {} --Instantiatable_class only shallow copies. So tables will not change, and thus some need to be initialized.
|
||||
def.property_modifiers = {}
|
||||
|
||||
--initialize all offsets
|
||||
--def.offsets = table.deep_copy(def.base_class.offsets)
|
||||
def.offsets = {}
|
||||
for i, tbl in pairs(def.base_class.offsets) do
|
||||
if (tbl.gun_axial and tbl.player_axial) then
|
||||
local ty = type(tbl.gun_axial)
|
||||
if (ty=="table") and tbl.gun_axial.x and tbl.gun_axial.y and tbl.gun_axial.z then
|
||||
def.offsets[i] = {}
|
||||
def.offsets[i].gun_axial = Vec.new()
|
||||
def.offsets[i].player_axial = Vec.new()
|
||||
else
|
||||
def.offsets[i] = {}
|
||||
def.offsets[i] = table.deep_copy(def.offsets[i])
|
||||
end
|
||||
elseif tbl.x and tbl.y and tbl.z then
|
||||
def.offsets[i] = Vec.new()
|
||||
end
|
||||
end
|
||||
def.velocities = table.deep_copy(gun.velocities)
|
||||
for i, tbl in pairs(def.velocities) do
|
||||
|
||||
|
||||
--def.velocities = table.deep_copy(def.base_class.velocities)
|
||||
def.velocities = {}
|
||||
for i, tbl in pairs(def.base_class.velocities) do
|
||||
def.velocities[i] = {}
|
||||
if tbl.gun_axial and tbl.player_axial then
|
||||
tbl.gun_axial = Vec.new(tbl.gun_axial)
|
||||
tbl.player_axial = Vec.new(tbl.player_axial)
|
||||
def.velocities[i].gun_axial = Vec.new()
|
||||
def.velocities[i].player_axial = Vec.new()
|
||||
end
|
||||
end
|
||||
--properties have been assigned, create necessary objects
|
||||
if def.properties.sprite_scope then
|
||||
if not def.sprite_scope then
|
||||
def.sprite_scope = def.properties.sprite_scope:new({
|
||||
gun = def
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
elseif def.name ~= "__template__" then
|
||||
local props = def.properties
|
||||
assert(def.name, "no name provided")
|
||||
assert(def.itemstring, "no itemstring provided")
|
||||
assert(minetest.registered_items[def.itemstring], "item is not registered, check dependencies.")
|
||||
|
||||
--override methods so control handler can do it's job
|
||||
local old_on_use = minetest.registered_items[def.itemstring].on_use
|
||||
local old_on_s_use = minetest.registered_items[def.itemstring].on_secondary_use
|
||||
@ -445,8 +464,9 @@ gun.construct = function(def)
|
||||
Guns4d.players[user:get_player_name()].handler.control_handler:on_secondary_use(itemstack, pointed_thing)
|
||||
end
|
||||
})
|
||||
def.properties = table.fill(def.parent_class.properties, def.properties or {})
|
||||
def.consts = table.fill(def.parent_class.consts, def.consts or {})
|
||||
|
||||
--(this tableref is ephermeral after constructor is called, see instantiatable_class)
|
||||
Guns4d.gun.registered[def.name] = def
|
||||
minetest.register_entity(def.name.."_visual", {
|
||||
initial_properties = {
|
||||
@ -480,14 +500,14 @@ gun.construct = function(def)
|
||||
if handler.control_bools.ads then
|
||||
|
||||
local normal_pos = (props.ads.offset+Vec.new(props.ads.horizontal_offset,0,0))*10
|
||||
obj:set_attach(player, gun.consts.AIMING_BONE, normal_pos, -axial_rot, visibility)
|
||||
obj:set_attach(player, lua_object.consts.AIMING_BONE, normal_pos, -axial_rot, visibility)
|
||||
else
|
||||
local normal_pos = Vec.new(props.hip.offset)*10
|
||||
-- Vec.multiply({x=normal_pos.x, y=normal_pos.z, z=-normal_pos.y}, 10)
|
||||
obj:set_attach(player, gun.consts.HIPFIRE_BONE, normal_pos, -axial_rot, visibility)
|
||||
obj:set_attach(player, lua_object.consts.HIPFIRE_BONE, normal_pos, -axial_rot, visibility)
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
Guns4d.gun = Instantiatable_class:inherit(gun)
|
||||
Guns4d.gun = Instantiatable_class:inherit(gun_default)
|
56
classes/Gun_ammo.lua
Normal file
56
classes/Gun_ammo.lua
Normal file
@ -0,0 +1,56 @@
|
||||
Gun_ammo = Instantiatable_class:inherit({
|
||||
name = "Gun_ammo_handler",
|
||||
construct = function(def)
|
||||
assert(def.gun)
|
||||
def.itemstack = def.gun.itemstack
|
||||
def.handler = def.gun.handler
|
||||
def.inventory = def.handler.inventory
|
||||
local meta = def.gun.meta
|
||||
|
||||
|
||||
|
||||
if gun.properties.magazine then
|
||||
local mag_meta = meta:get_string("guns4d_loaded_mag")
|
||||
if mag_meta == "" then
|
||||
meta:set_string("guns4d_loaded_mag", gun.properties.magazine.comes_with or "empty")
|
||||
meta:set_string("guns4d_loaded_bullets", minetest.serialize({}))
|
||||
else
|
||||
def.mag = mag_meta
|
||||
def.bullets = minetest.deserialize(meta:get_string("guns4d_loaded_bullets"))
|
||||
end
|
||||
else
|
||||
local bullet_meta = meta:get_string("guns4d_loaded_bullets")
|
||||
if bullet_meta == "" then
|
||||
meta:set_string("guns4d_loaded_bullets", minetest.serialize({}))
|
||||
else
|
||||
def.ammo.bullets = minetest.deserailize(bullet_meta)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
function Gun_ammo:load_mag()
|
||||
local inv = self.inventory
|
||||
for _, ammunition in pairs(self.gun.accepted_mags) do
|
||||
for i = 1, inv:get_size("main") do
|
||||
|
||||
end
|
||||
end
|
||||
if magstack then
|
||||
ammo_table = minetest.deserialize(magstack:get_meta():get_string("ammo"))
|
||||
inv:set_stack("main", index, "")
|
||||
state = next_state
|
||||
state_changed = true
|
||||
end
|
||||
end
|
||||
function Gun_ammo:unload_mag()
|
||||
end
|
||||
function Gun_ammo:load_magless()
|
||||
end
|
||||
function Gun_ammo:unload_magless()
|
||||
end
|
||||
function Gun_ammo:load_fractional()
|
||||
end
|
||||
function Gun_ammo:unload_fractional()
|
||||
end
|
||||
function Gun_ammo:unload_chamber()
|
||||
end
|
@ -4,7 +4,8 @@ Instantiatable_class = {
|
||||
--not that construction change is NOT called for inheriting an object.
|
||||
function Instantiatable_class:inherit(def)
|
||||
--construction chain for inheritance
|
||||
if not def then def = {} else def = table.shallow_copy(def) end
|
||||
--if not def then def = {} else def = table.shallow_copy(def) end
|
||||
def.parent_class = self
|
||||
def.instance = false
|
||||
def._construct_low = def.construct
|
||||
--this effectively creates a construction chain by overwriting .construct
|
||||
@ -17,13 +18,15 @@ function Instantiatable_class:inherit(def)
|
||||
self.construct(parameters)
|
||||
end
|
||||
end
|
||||
--print("CONSTRUCTED")
|
||||
def.construct(def)
|
||||
--iterate through table properties
|
||||
setmetatable(def, {__index = self})
|
||||
return def
|
||||
end
|
||||
function Instantiatable_class:new(def)
|
||||
if not def then def = {} else def = table.shallow_copy(def) end
|
||||
--if not def then def = {} else def = table.shallow_copy(def) end
|
||||
def.base_class = self
|
||||
def.instance = true
|
||||
function def:inherit(def)
|
||||
assert(false, "cannot inherit instantiated object")
|
||||
|
49
classes/Modifier.lua
Normal file
49
classes/Modifier.lua
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
function table.resolve_string(object, address)
|
||||
local indexes = string.split(address)
|
||||
local current
|
||||
for i, v in pairs(indexes) do
|
||||
current = current[i]
|
||||
end
|
||||
return current
|
||||
end
|
||||
local function split_into_adresses(object, path, out)
|
||||
out = out or {}
|
||||
path = path or ""
|
||||
for index, val in pairs(object) do
|
||||
local this_path = path.."."..index
|
||||
if type(val) == "table" then
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
return out
|
||||
end
|
||||
Modifier = Instantiatable_class:inherit({
|
||||
overwrites = {},
|
||||
construct = function(def)
|
||||
if def.instance then
|
||||
assert(type(def.apply)=="function", "no application function found for modifier")
|
||||
assert(def.name, "name is required for modifiers")
|
||||
assert(def.properties, "cannot modify a nonexisent properties table")
|
||||
local old_apply = def.apply
|
||||
def.is_active = false
|
||||
def.immutable_props = Proxy_table:get_or_create()
|
||||
function def.apply(properties)
|
||||
assert(not def.is_active, "attempt to double apply modifier '"..def.name.."'")
|
||||
def.is_active = true
|
||||
local proxy = Proxy_table:get_or_create(properties) --the proxy prevents unintended modification of the original table.
|
||||
local add_table, override_table = old_apply(proxy)
|
||||
if add_table then
|
||||
|
||||
end
|
||||
if override_table then
|
||||
|
||||
end
|
||||
end
|
||||
function def.stop()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
})
|
@ -20,7 +20,7 @@ function player_handler:update(dt)
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
local player = self.player
|
||||
self.wielded_item = self.player:get_wielded_item()
|
||||
local held_gun = self:is_holding_Gun() --get the gun class that is associated with the held gun
|
||||
local held_gun = self:is_holding_gun() --get the gun class that is associated with the held gun
|
||||
if held_gun then
|
||||
--was there a gun last time? did the wield index change?
|
||||
local old_index = self.wield_index
|
||||
@ -28,22 +28,21 @@ function player_handler:update(dt)
|
||||
|
||||
--initialize all handlers and objects
|
||||
if (not self.gun) or (self.gun.id ~= self.wielded_item:get_meta():get_string("guns4d_id")) then
|
||||
--initialize all handlers
|
||||
|
||||
--initialize important player data
|
||||
self.itemstack = self.wielded_item
|
||||
self.inventory = player:get_inventory()
|
||||
----gun (handler w/physical manifestation)----
|
||||
if self.gun then --delete gun object if present
|
||||
self.gun:prepare_deletion()
|
||||
self.gun = nil
|
||||
end
|
||||
self.gun = held_gun:new({itemstack=self.wielded_item, player=self.player, handler=self}) --this will set itemstack meta, and create the gun based off of meta and other data.
|
||||
|
||||
self.gun = held_gun:new({itemstack=self.wielded_item, handler=self}) --this will set itemstack meta, and create the gun based off of meta and other data.
|
||||
----model handler----
|
||||
if self.model_handler then --if model_handler present, then delete
|
||||
self.model_handler:prepare_deletion()
|
||||
self.model_handler = nil
|
||||
end
|
||||
self.model_handler = model_handler.get_handler(self:get_properties().mesh):new({player=self.player})
|
||||
|
||||
----control handler----
|
||||
self.control_handler = Guns4d.control_handler:new({player=player, controls=self.gun.properties.controls})
|
||||
--reinitialize some handler data and set set_hud_flags
|
||||
@ -51,7 +50,6 @@ function player_handler:update(dt)
|
||||
player:hud_set_flags({wielditem = false, crosshair = false})
|
||||
|
||||
end
|
||||
|
||||
--update some properties.
|
||||
self.look_rotation.x, self.look_rotation.y = player:get_look_vertical()*180/math.pi, -player:get_look_horizontal()*180/math.pi
|
||||
if TICK % 10 == 0 then
|
||||
@ -163,7 +161,7 @@ function player_handler:set_properties(properties)
|
||||
self.player:set_properties(properties)
|
||||
self.properties = table.fill(self.properties, properties)
|
||||
end
|
||||
function player_handler:is_holding_Gun()
|
||||
function player_handler:is_holding_gun()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
if self.wielded_item then
|
||||
for name, obj in pairs(Guns4d.gun.registered) do
|
||||
|
58
classes/Proxy_table.lua
Normal file
58
classes/Proxy_table.lua
Normal file
@ -0,0 +1,58 @@
|
||||
Proxy_table = {
|
||||
registered_proxies = {},
|
||||
proxy_children = {}
|
||||
}
|
||||
--this creates proxy tables in a structure of tables
|
||||
--this is great if you want to prevent the change of a table
|
||||
--but still want it to be viewable, such as with constants
|
||||
function Proxy_table:new(og_table, parent)
|
||||
local new = {}
|
||||
self.registered_proxies[og_table] = new
|
||||
if parent then
|
||||
self.proxy_children[parent][og_table] = true
|
||||
else
|
||||
self.proxy_children[og_table] = {}
|
||||
parent = og_table
|
||||
end
|
||||
--set the proxy's metatable
|
||||
setmetatable(new, {
|
||||
__index = function(t, key)
|
||||
if type(og_table[key]) == "table" then
|
||||
return Proxy_table:get_or_create(og_table[key], parent)
|
||||
else
|
||||
return og_table[key]
|
||||
end
|
||||
end,
|
||||
__newindex = function(table, key)
|
||||
assert(false, "attempt to edit immutable table, cannot edit a proxy")
|
||||
end,
|
||||
})
|
||||
--[[overwrite og_table meta to destroy the proxy aswell (but I realized it wont be GCed unless it's removed altogether, so this is pointless)
|
||||
local mtable = getmetatable(og_table)
|
||||
local old_gc = mtable.__gc
|
||||
mtable.__gc = function(t)
|
||||
self.registered_proxies[t] = nil
|
||||
self.proxy_children[t] = nil
|
||||
old_gc(t)
|
||||
end
|
||||
setmetatable(og_table, mtable)]]
|
||||
--premake proxy tables
|
||||
for i, v in pairs(og_table) do
|
||||
if type(v) == "table" then
|
||||
Proxy_table:get_or_create(v, parent)
|
||||
end
|
||||
end
|
||||
return new
|
||||
end
|
||||
function Proxy_table:get_or_create(og_table, parent)
|
||||
return self.registered_proxies[og_table] or Proxy_table:new(og_table, parent)
|
||||
end
|
||||
function Proxy_table:destroy_proxy(parent)
|
||||
self.registered_proxies[parent] = nil
|
||||
if self.proxy_children[parent] then
|
||||
for i, v in pairs(self.proxy_children[parent]) do
|
||||
Proxy_table:destroy_proxy(i)
|
||||
end
|
||||
end
|
||||
self.proxy_children[parent] = nil
|
||||
end
|
@ -2,7 +2,7 @@ Sprite_scope = Instantiatable_class:inherit({
|
||||
images = {
|
||||
fore = {
|
||||
texture = "scope_fore.png",
|
||||
scale = {x=10,y=10},
|
||||
scale = {x=11,y=11},
|
||||
movement_multiplier = 1,
|
||||
},
|
||||
back = {
|
||||
|
18
docs/future control scheme ideas.txt
Normal file
18
docs/future control scheme ideas.txt
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
z = reload
|
||||
tap shift+z = switch fire mode
|
||||
|
||||
while aiming
|
||||
q-e = aux switch leaning side/aiming side (default is always right)
|
||||
|
||||
while hip
|
||||
e = aux
|
||||
hold shift+z = open gun menu
|
||||
q = drop the weapon
|
||||
|
||||
gun menu
|
||||
turn safety on (can be turned off with shift+z)
|
||||
unload weapon
|
||||
set preferred ammo type(s)
|
||||
set preferred ammo type weighting(?) (allow for control over when there's not enough ammo in a mag to prefer it)
|
||||
add modifications
|
14
docs/modifier class.txt
Normal file
14
docs/modifier class.txt
Normal file
@ -0,0 +1,14 @@
|
||||
The modifier class is a class that's used to specify
|
||||
specific changes to a gun's properties.
|
||||
|
||||
to make a modifier, do something like this
|
||||
Modifier:new({
|
||||
apply = function(properties)
|
||||
--absolutely DO NOT EVER change properties here
|
||||
--this function is only so you can calculate changes
|
||||
--based on the properties of the gun.
|
||||
return {
|
||||
|
||||
}
|
||||
end
|
||||
})
|
@ -1,4 +1,6 @@
|
||||
|
||||
|
||||
|
||||
VFX, SFX:
|
||||
Bullet hit node FX (steal mostly from 3dguns)
|
||||
Bullet fly-by SFX
|
||||
@ -20,6 +22,8 @@ gun features
|
||||
"3d" optics
|
||||
attachments (last before beta)
|
||||
fix shooting through walls be pressing against them
|
||||
correct player look-down
|
||||
gun leaning
|
||||
|
||||
bullets
|
||||
bullet class system
|
||||
|
@ -53,11 +53,9 @@ local default_def = {
|
||||
if not handler.control_handler.busy_list.on_use then
|
||||
handler.gun:fire()
|
||||
end
|
||||
print(handler.control_handler.busy_list.on_use)
|
||||
end
|
||||
},
|
||||
on_use = function(itemstack, handler, pointed_thing)
|
||||
print("use")
|
||||
handler.gun:fire()
|
||||
handler.control_handler.busy_list.on_use = true
|
||||
end
|
||||
|
1
init.lua
1
init.lua
@ -15,6 +15,7 @@ dofile(path.."/Sprite_scope.lua")
|
||||
dofile(path.."/Gun.lua")
|
||||
dofile(path.."/Player_model_handler.lua")
|
||||
dofile(path.."/Player_handler.lua")
|
||||
dofile(path.."/Proxy_table.lua")
|
||||
|
||||
--load after
|
||||
path = minetest.get_modpath("guns4d")
|
||||
|
@ -58,6 +58,56 @@ function table.deep_copy(tbl, copy_metatable, indexed_tables)
|
||||
end
|
||||
return new_table
|
||||
end
|
||||
|
||||
|
||||
function table.contains(tbl, value)
|
||||
for i, v in pairs(tbl) do
|
||||
if v == value then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local function parse_index(i)
|
||||
if type(i) == "string" then
|
||||
return "[\""..i.."\"]"
|
||||
else
|
||||
return "["..tostring(i).."]"
|
||||
end
|
||||
end
|
||||
--dump() sucks.
|
||||
function table.tostring(tbl, shallow, tables, depth)
|
||||
--create a list of tables that have been tostringed in this chain
|
||||
if not table then return "nil" end
|
||||
if not tables then tables = {this_table = tbl} end
|
||||
if not depth then depth = 0 end
|
||||
depth = depth + 1
|
||||
local str = "{"
|
||||
local initial_string = "\n"
|
||||
for i = 1, depth do
|
||||
initial_string = initial_string .. " "
|
||||
end
|
||||
for i, v in pairs(tbl) do
|
||||
local val_type = type(v)
|
||||
if val_type == "string" then
|
||||
str = str..initial_string..parse_index(i).." = \""..v.."\","
|
||||
elseif val_type == "table" and (not shallow) then
|
||||
local contains = table.contains(tables, v)
|
||||
--to avoid infinite loops, make sure that the table has not been tostringed yet
|
||||
if not contains then
|
||||
tables[i] = v
|
||||
str = str..initial_string..parse_index(i).." = "..table.tostring(v, shallow, tables, depth)..","
|
||||
else
|
||||
str = str..initial_string..parse_index(i).." = "..tostring(v).." ("..contains.."),"
|
||||
end
|
||||
else
|
||||
str = str..initial_string..parse_index(i).." = "..tostring(v)..","
|
||||
end
|
||||
end
|
||||
return str..string.sub(initial_string, 1, -5).."}"
|
||||
end
|
||||
|
||||
|
||||
--replace elements in tbl with elements in replacement, but preserve the rest
|
||||
function table.fill(tbl, replacement, preserve_reference, indexed_tables)
|
||||
if not indexed_tables then indexed_tables = {} end --store tables to prevent circular referencing
|
||||
|
46
register_ammo.lua
Normal file
46
register_ammo.lua
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
Default_bullet = {
|
||||
registered = {},
|
||||
range = 100,
|
||||
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
|
||||
}
|
||||
Guns4d.ammo = {
|
||||
registered_bullets = {
|
||||
|
||||
},
|
||||
registered_magazines = {
|
||||
|
||||
}
|
||||
}
|
||||
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
|
||||
end
|
||||
--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
|
||||
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)
|
||||
--register the actual recipe to add ammo to a mag
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user