tons of changes, probably, not sure

This commit is contained in:
FatalErr42O 2023-08-29 12:40:36 -07:00
parent 295cd8fa79
commit 6ec442ee31
15 changed files with 343 additions and 127 deletions

View File

@ -17,8 +17,6 @@ Guns4d.node_properties = {}
--in a perfect world you could perfectly balance each node, but a aproximation will have to do
--luckily its still an option, if you are literally out of your fucking mind.
minetest.register_on_mods_loaded(function()
print(table.tostring(minetest.registered_nodes["stairs:slab_wood"].groups))
print(table.tostring(minetest.registered_nodes["default:wood"].groups))
for i, v in pairs(minetest.registered_nodes) do
local groups = v.groups
local RHA = 1

View File

@ -82,7 +82,6 @@ function Ammo_handler:load_magazine()
if ammo > highest_ammo then
highest_ammo = ammo
local has_unaccepted = false
print(meta:get_string("guns4d_loaded_bullets"))
for bullet, _ in pairs(minetest.deserialize(meta:get_string("guns4d_loaded_bullets"))) do
if not gun.accepted_bullets[bullet] then
has_unaccepted = true
@ -138,7 +137,6 @@ end
function Ammo_handler:unload_magazine(to_ground)
assert(self.instance, "attempt to call object method on a class")
if self.ammo.loaded_mag ~= "empty" then
minetest.chat_send_all("not empty")
local inv = self.handler.inventory
local magstack = ItemStack(self.ammo.loaded_mag)
local magmeta = magstack:get_meta()

View File

@ -9,16 +9,11 @@ local ray = {
--exit_direction = dir,
--range_left = def.bullet.range,
--energy = def.bullet.penetration_RHA
mmRHA_to_Pa_energy_ratio = .5,
ITERATION_DISTANCE = .3,
damage = 0
}
function ray:record_state()
table.insert(self.history, {
state = self.state
})
end
--find (valid) edge. Slabs or other nodeboxes that are not the last hit position are not considered (to account for holes) TODO: update to account for hollow nodes
function ray:find_transverse_edge()
assert(self.instance, "attempt to call obj method on a class")
@ -65,7 +60,7 @@ function ray:_cast()
local pointed_object
for hit in cast do
local h_length = vector.distance(hit.intersection_point, self.pos)
if ( (not hit.ref) and h_length > 0.0001) and h_length < self.range then
if (h_length > 0.0001) and h_length < self.range then
--if it's a node, check that it's note supposed to be ignored according to it's generated properties
if hit.type == "node" then
if self.state == "free" and Guns4d.node_properties[minetest.get_node(hit.under).name].behavior ~= "ignore" then
@ -97,8 +92,6 @@ function ray:_cast()
--if it's an object, make sure it's not the player object
--note that while it may seem like this will create a infinite hit loop, it resolves itself as the intersection_point of the next ray will be close enough as to skip the pointed. See first line of iterator.
if (hit.type == "object") and (hit.ref ~= self.player) and ((not self.last_pointed_object) or (hit.ref ~= self.last_pointed_object.ref)) then
minetest.chat_send_all("ent hit, ray")
end_pos = pointed_object.intersection_point
if self.over_penetrate then
pointed_object = hit
break
@ -107,6 +100,7 @@ function ray:_cast()
continue = false
break
end
end_pos = pointed_object.intersection_point
end
end
end
@ -133,7 +127,7 @@ function ray:_iterate(initialized)
end
local penetration_loss = distance*Guns4d.node_properties[self.last_node_name].mmRHA
--calculate our energy loss based on the percentage of energy our penetration represents.
self.energy = self.energy-((self.init_energy*self.energy_sharp_ratio)*(penetration_loss/self.init_penetration))
self.energy = self.energy-((self.init_energy*self.energy_sharp_ratio)*(penetration_loss/self.sharp_penetration))
end
if self.state ~= self.next_state then
@ -148,7 +142,7 @@ function ray:_iterate(initialized)
if pointed_object then
self.pos = pointed_object.intersection_point
self.last_pointed_object = pointed_object
ray:hit_entity(pointed_object.ref)
self:hit_entity(pointed_object.ref)
else
self.pos = end_pos
end
@ -166,7 +160,7 @@ function ray:_iterate(initialized)
if continue and self.range > 0 and self.energy > 0 then
self:_iterate(true)
end
if not initialized then
--[[if not initialized then
for i, v in pairs(self.history) do
local hud = self.player:hud_add({
hud_elem_type = "waypoint",
@ -182,19 +176,64 @@ function ray:_iterate(initialized)
self.player:hud_remove(hud)
end, hud)
end
end]]
end
--can be safely overridden
function ray:calculate_sharp_conversion(resistance, sharp_penetration)
assert(self.instance, "attempt to call obj method on a class")
end
function ray:hit_entity(object)
assert(self.instance, "attempt to call obj method on a class")
local resistance = object:get_armor_groups() -- support for different body parts is needed here, that's for... a later date, though.
local sharp_pen = self.sharp_penetration-(self.sharp_penetration*(self.energy/self.init_energy)*self.energy_sharp_ratio)
sharp_pen = math.clamp(sharp_pen - (resistance.guns4d_mmRHA or 0), 0, 65535)
local converted_Pa = (resistance.guns4d_mmRHA or 0) * self.mmRHA_to_Pa_energy_ratio
local blunt_pen = converted_Pa+(self.blunt_penetration-(self.blunt_penetration*(self.energy/self.init_energy)*(1-self.energy_sharp_ratio)))
blunt_pen = math.clamp(blunt_pen - (resistance.guns4d_Pa or 0), 0, 65535)
self:apply_damage(object, sharp_pen, blunt_pen)
--raw damage first
end
--not point in overriding this if you remove hit_entity()
--blunt & sharp ratio are the ratios of initial damage to damage at this bullet's current energy.
function ray:apply_damage(object, sharp_pen, blunt_pen)
assert(self.instance, "attempt to call obj method on a class")
--coefficients for damage
local blunt_ratio = blunt_pen/self.blunt_penetration
local sharp_ratio = sharp_pen/self.sharp_penetration
--raw damage values
local blunt_dmg = self.raw_blunt_damage*blunt_ratio
local sharp_dmg = self.raw_sharp_damage*sharp_ratio
local hp = (object:get_hp()-blunt_dmg)-sharp_dmg
print(blunt_dmg, sharp_dmg, blunt_ratio, sharp_ratio)
print(self.blunt_penetration, self.sharp_penetration)
if hp < 0 then hp = 0 end
object:set_hp(hp, {type="set_hp", from="guns4d"})
--now apply damage groups.
if self.blunt_damage_groups then
local damage_values = {}
for i, v in pairs(self.blunt_damage_groups) do
damage_values[i] = v*blunt_ratio
end
object:punch(self.gun.entity, 1000, {damage_groups=damage_values}, self.dir)
end
end
function ray:calculate_sharp_conversion(bullet, armor, groups)
end
function ray:calculate_sharp_damage(bullet, armor, groups)
end
function ray:calculate_blunt_damage(bullet, armor, groups)
end
function ray:apply_damage(object, blunt_pen, sharp_pen, blunt_dmg, sharp_dmg)
minetest.chat_send_all("ent hit")
object:punch()
if self.sharp_damage_groups then
local damage_values = {}
for i, v in pairs(self.sharp_damage_groups) do
damage_values[i] = v*sharp_ratio
end
object:punch(self.gun.entity, 1000, {damage_groups=damage_values}, self.dir)
end
--punch SUCKS for this, apparently armor can only have flat rates of protection, which is sort of the worst thing i've ever heard.
--object:punch()
end
function ray:bullet_hole(pos, normal)
assert(self.instance, "attempt to call obj method on a class")
local nearby_players = false
for pname, player in pairs(minetest.get_connected_players()) do
if vector.distance(player:get_pos(), pos) < 50 then
@ -222,21 +261,33 @@ function ray.construct(def)
assert(def.range, "no range")
assert(def.energy, "no energy")
assert(def.energy_dropoff, "no energy dropoff")
assert(def.blunt_damage, "no blunt damage")
def.sharp_damage = def.sharp_damage or 0
def.sharp_penetration = def.sharp_penetration or 0
if def.sharp_penetration==0 then
def.blunt_penetration = def.blunt_penetration or def.energy/2
else
def.blunt_penetration = def.blunt_penetration or def.energy
--use this if you don't want to use the built-in system for penetrations.
assert(not(def.ignore_penetration and not rawget(def, "hit_entity")), "bullet ray cannot ignore default penetration if hit_entity() is undefined. Use ignore_penetration for custom damage systems." )
if not def.ignore_penetration then
assert((not (def.blunt_penetration and def.energy)) or (def.blunt_penetration < def.energy), "blunt penetration may not be greater than energy! Blunt penetration is in Joules/Megapascals, energy is also in Joules.")
--"raw" damages define the damage (unaffected by armor groups) for the initial penetration value of each type.
--def.sharp_damage_groups = {} --tool capabilities
--def.blunt_damage_groups = {}
--guns4d mmRHA is used in traditional context.
assert((not def.blunt_damage_groups) or not def.blunt_damage_groups["guns4d_mmRHA"], "guns4d_mmRHA damage group is not used in a traditional context. To increase penetration, increase sharp_penetration field.")
assert((not def.blunt_damage_groups) or not def.blunt_damage_groups["guns4d_Pa"], "guns4d_Pa is not used in a traditional context. To increase blunt penetration, increase blunt_penetration field.")
def.raw_sharp_damage = def.raw_sharp_damage or 0
def.raw_blunt_damage = def.raw_blunt_damage or 0
def.sharp_penetration = def.sharp_penetration or 0
if def.sharp_penetration==0 then
def.blunt_penetration = def.blunt_penetration or def.energy/2
else
def.blunt_penetration = def.blunt_penetration or def.energy
end
def.energy_sharp_ratio = (def.energy-def.blunt_penetration)/def.energy
end
def.init_energy = def.energy
def.init_penetration = def.sharp_penetration
def.init_blunt = def.blunt_penetration
--blunt pen is in the same units (1 Joule/Area^3 = 1 MPa), so we use it to make the ratio by subtraction.
def.energy_sharp_ratio = (def.energy-def.blunt_penetration)/def.energy
--blunt pen is in the same units (1 Joule/Area^3 = 1 Pa), so we use it to make the ratio by subtraction.
def.dir = vector.new(def.dir)
def.pos = vector.new(def.pos)

View File

@ -144,13 +144,69 @@ local gun_default = {
muzzle_flash = Guns4d.effects.muzzle_flash
}
--update the gun, da meat and da potatoes
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(); self:clear_animation() end
local handler = self.handler
local look_rotation = {x=handler.look_rotation.x,y=handler.look_rotation.y}
local total_rot = self.offsets.total_offset_rotation
local player_rot = self.offsets.player_rotation
local constant = 6
--player look rotation. I'm going to keep it real, I don't remember what this equation does.
if not self.sprite_scope then
local next_vert_aim = ((player_rot.x+look_rotation.x)/(1+constant*dt))-look_rotation.x
if math.abs(look_rotation.x-next_vert_aim) > .005 then
player_rot.x = next_vert_aim
else
player_rot.x = -look_rotation.x
end
else
player_rot.x = -look_rotation.x
end
--timers
if self.rechamber_time > 0 then
self.rechamber_time = self.rechamber_time - dt
else
self.rechamber_time = 0
end
self.time_since_creation = self.time_since_creation + dt
self.time_since_last_fire = self.time_since_last_fire + dt
--update some vectors
if self.consts.HAS_SWAY then self:update_sway(dt) end
if self.consts.HAS_RECOIL then self:update_recoil(dt) end
if self.consts.HAS_BREATHING then self:update_breathing(dt) end
if self.consts.HAS_WAG then self:update_wag(dt) end
self.dir = self:get_dir()
self.local_dir = self:get_dir(true)
self.paxial_dir = self:get_player_axial_dir()
self.local_paxial_dir = self:get_player_axial_dir(true)
self.pos = self:get_pos()
local bone, quat = self.model_handler:get_bone_global("Magazine")
minetest.chat_send_all(dump(bone))
--minetest.chat_send_all(dump(quat))
self:get_pos(bone/10, true)
--sprite scope
if self.properties.sprite_scope then
self.sprite_scope:update()
end
player_rot.y = -handler.look_rotation.y
local offsets = self.offsets
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}
total_rot.gun_axial = offsets.recoil.gun_axial + offsets.walking.gun_axial + offsets.sway.gun_axial
end
function gun_default:attempt_fire()
assert(self.instance, "attempt to call object method on a class")
if self.rechamber_time <= 0 then
local spent_bullet = self.ammo_handler:spend_round()
if spent_bullet then
local dir = self.dir
local pos = self:get_pos()
local pos = self.pos
--[[print(dump(Guns4d.ammo.registered_bullets))
print(self.ammo_handler.next_bullet)
print(Guns4d.ammo.registered_bullets[self.ammo_handler.next_bullet])]]
@ -192,7 +248,7 @@ function gun_default:get_player_axial_dir(rltv)
local dir = Vec.new(Vec.rotate({x=0, y=0, z=1}, {y=0, x=((rotation.player_axial.x)*math.pi/180), z=0}))
dir = Vec.rotate(dir, {y=((rotation.player_axial.y)*math.pi/180), x=0, z=0})
if not rltv then
dir = Vec.rotate(dir, {x=self.offsets.player_rotation.x*(math.pi/180),y=0,z=0})
dir = Vec.rotate(dir, {x=self.offsets.player_rotation.x*math.pi/180,y=self.offsets.player_rotation.y*math.pi/180,z=0})
end
--[[local hud_pos = Vec.rotate(dir, {x=0,y=self.offsets.player_rotation.y*math.pi/180,z=0})+player:get_pos()+{x=0,y=player:get_properties().eye_height,z=0}+vector.rotate(player:get_eye_offset()/10, {x=0,y=self.offsets.player_rotation.y*math.pi/180,z=0})
local hud = player:hud_add({
@ -232,30 +288,35 @@ function gun_default:get_dir(rltv)
return dir
end
function gun_default:get_pos(added_pos)
--broken! doesn't properly reflect values.
function gun_default:get_pos(added_pos, debug)
assert(self.instance, "attempt to call object method on a class")
added_pos = Vec.new(added_pos)
local player = self.player
local handler = self.handler
local bone_location = Vec.new(handler.model_handler.offsets.arm.right)/10
local gun_offset = Vec.new(self.properties.hip.offset)
local player_rotation = Vec.new(self.offsets.player_rotation.x, self.offsets.player_rotation.y, 0)
local bone_location
local gun_offset
if handler.control_bools.ads then
gun_offset = self.properties.ads.offset
bone_location = Vec.new(0, handler:get_properties().eye_height, 0)+player:get_eye_offset()/10
bone_location, _ = player:get_eye_offset() or vector.zero(), nil
bone_location.y = bone_location.y + handler:get_properties().eye_height
bone_location.x = handler.horizontal_offset
else
--minetest is really wacky.
bone_location.x = -bone_location.x
player_rotation.x = self.offsets.player_rotation.x*self.consts.HIP_PLAYER_GUN_ROT_RATIO
gun_offset = self.properties.hip.offset
bone_location = handler.model_handler.offsets.arm.right
bone_location.x = -bone_location.x / 10
bone_location.z = bone_location.z / 10
bone_location.y = bone_location.y / 10
end
if added_pos then
gun_offset = gun_offset+added_pos
end
gun_offset = gun_offset+added_pos
--dir needs to be rotated twice seperately to avoid weirdness
local rotation = self.offsets.total_offset_rotation
local bone_pos = Vec.rotate(bone_location, {x=0, y=player_rotation.y*math.pi/180, z=0})
local gun_offset = Vec.rotate(Vec.rotate(gun_offset, {x=(rotation.player_axial.x+player_rotation.x)*math.pi/180,y=0,z=0}), {x=0,y=(rotation.player_axial.y+player_rotation.y)*math.pi/180,z=0})
--[[local hud_pos = bone_pos+gun_offset+handler:get_pos()
if not false then
local pos = Vec.rotate(bone_location, {x=0, y=-handler.look_rotation.y*math.pi/180, z=0})
pos = pos+Vec.rotate(gun_offset, Vec.dir_to_rotation(self.paxial_dir))
local hud_pos = pos+handler:get_pos()
if debug then
local hud = player:hud_add({
hud_elem_type = "image_waypoint",
text = "muzzle_flash2.png",
@ -267,9 +328,9 @@ function gun_default:get_pos(added_pos)
minetest.after(0, function(hud)
player:hud_remove(hud)
end, hud)
end]]
end
--world pos, position of bone, offset of gun from bone (with added_pos)
return bone_pos+gun_offset+handler:get_pos(), bone_pos, gun_offset
return pos
end
function gun_default:add_entity()
@ -277,6 +338,7 @@ function gun_default:add_entity()
self.entity = minetest.add_entity(self.player:get_pos(), self.name.."_visual")
local obj = self.entity:get_luaentity()
obj.parent_player = self.player
Guns4d.gun_by_ObjRef[self.entity] = self
obj:on_step()
end
@ -286,59 +348,6 @@ function gun_default:has_entity()
if not self.entity:get_pos() then return false end
return true
end
--update the gun, da meat and da potatoes
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(); self:clear_animation() end
self.pos = self:get_pos()
local handler = self.handler
local look_rotation = {x=handler.look_rotation.x,y=handler.look_rotation.y}
local total_rot = self.offsets.total_offset_rotation
local player_rot = self.offsets.player_rotation
local constant = 6
--player look rotation. I'm going to keep it real, I don't remember what this equation does.
if not self.sprite_scope then
local next_vert_aim = ((player_rot.x+look_rotation.x)/(1+constant*dt))-look_rotation.x
if math.abs(look_rotation.x-next_vert_aim) > .005 then
player_rot.x = next_vert_aim
else
player_rot.x = -look_rotation.x
end
else
player_rot.x = -look_rotation.x
end
--timers
if self.rechamber_time > 0 then
self.rechamber_time = self.rechamber_time - dt
else
self.rechamber_time = 0
end
self.time_since_creation = self.time_since_creation + dt
self.time_since_last_fire = self.time_since_last_fire + dt
--update some vectors
if self.consts.HAS_SWAY then self:update_sway(dt) end
if self.consts.HAS_RECOIL then self:update_recoil(dt) end
if self.consts.HAS_BREATHING then self:update_breathing(dt) end
if self.consts.HAS_WAG then self:update_wag(dt) end
self.dir = self:get_dir()
self.local_dir = self:get_dir(true)
self.paxial_dir = self:get_player_axial_dir()
self.local_paxial_dir = self:get_player_axial_dir(true)
--sprite scope
if self.properties.sprite_scope then
self.sprite_scope:update()
end
player_rot.y = -handler.look_rotation.y
local offsets = self.offsets
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}
total_rot.gun_axial = offsets.recoil.gun_axial + offsets.walking.gun_axial + offsets.sway.gun_axial
end
function gun_default:update_wag(dt)
local handler = self.handler
if handler.walking then
@ -531,6 +540,8 @@ gun_default.construct = function(def)
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())
@ -612,6 +623,9 @@ gun_default.construct = function(def)
def.consts = table.fill(def.parent_class.consts, def.consts or {})
props = def.properties --have to reinitialize this as the reference is replaced.
--print(table.tostring(props))
def.model_handler = Guns4d.Model_bone_handler:new({modelpath = props.mesh})
if def.name ~= "__template" then
assert(rawget(def, "name"), "no name provided in new class")
assert(rawget(def, "itemstring"), "no itemstring provided in new class")
@ -687,8 +701,9 @@ gun_default.construct = function(def)
-- Vec.multiply({x=normal_pos.x, y=normal_pos.z, z=-normal_pos.y}, 10)
obj:set_attach(player, lua_object.consts.HIPFIRE_BONE, normal_pos, -axial_rot, visibility)
end
end
end,
})
--I don't know why lua's syntax makes me make it anon, but uh, fuck you.
end
end
Guns4d.gun = Instantiatable_class:inherit(gun_default)

117
classes/Model_reader.lua Normal file
View File

@ -0,0 +1,117 @@
local path_seperator = "/@/"
Guns4d.Model_bone_handler = Instantiatable_class:inherit({
construct = function(def)
if def.instance then
assert(def.modelpath, "no path provided")
if mtul.media_paths[def.modelpath] then def.modelpath = mtul.media_paths[def.modelpath] end
local stream = io.open(def.modelpath, "rb")
def.b3d_table = mtul.b3d.read(stream)
stream:close()
stream = minetest.request_insecure_environment().io.open(minetest.get_modpath("guns4d").."/test.gltf", "wb")
modlib.b3d.write_gltf(def.b3d_table, stream)
stream:close()
def.paths = {}
def:process_and_reformat()
end
end
})
local model_bones = Guns4d.Model_bone_handler
--this creates a list of bone paths, and changes the index from an int to names.
local function retrieve_hierarchy(node, out)
if not out then out = {node} end
if node.parent then
table.insert(out, 1, node.parent)
retrieve_hierarchy(node.parent, out)
end
return out
end
function model_bones:solve_global_transform(node)
assert(self.instance, "attempt to call object method on a class")
local global_transform
local hierarcy = retrieve_hierarchy(node)
print("start")
for i, v in pairs(hierarcy) do
print(i, v.name)
end
print("end")
for i, v in pairs(hierarcy) do
local pos_vec = v.position
local rot_vec = v.rotation
local scl_vec = v.scale
if v.keys[2] then
pos_vec = v.keys[2].position
rot_vec = v.keys[2].rotation
scl_vec = v.keys[2].scale
end
--rot_vec = {rot_vec[2], rot_vec[3], rot_vec[4], rot_vec[1]}
pos_vec = {-pos_vec[1], pos_vec[2], pos_vec[3]}
local pos = modlib.matrix4.translation(pos_vec)
rot_vec = {-rot_vec[1], rot_vec[2], rot_vec[3], rot_vec[4]}
local rot = modlib.matrix4.rotation(modlib.quaternion.normalize(rot_vec))
local scl = modlib.matrix4.scale(scl_vec)
local local_transform = scl:compose(rot):compose(pos)
if global_transform then
global_transform=global_transform:multiply(local_transform)
else
global_transform=local_transform
end
end
local pos
if node.keys[2] then
pos = node.position
else
pos = node.keys[2].position
end
--pos = global_transform:apply({pos[1], pos[2], pos[3], 1})
--print(dump(global_transform))
--return vector.new(pos[1], pos[2], pos[3])
return vector.new(global_transform[1][4], global_transform[2][4], global_transform[3][4])
end
function model_bones:get_bone_global(bone_name)
assert(self.instance, "attempt to call object method on a class")
for i, v in pairs(self.paths) do
local s, e = string.find(i, bone_name, #i-#bone_name)
--this needs to be fixed.
if s then
local v1, v2 = self:solve_global_transform(v)
return v1, v2
end
end
end
function model_bones:process_and_reformat(node, path)
assert(self.instance, "attempt to call object method on a class")
local first = false
if not node then
first = true
node = self.b3d_table.node
end
path = path or ""
node.mesh = nil --we wont be needing this
for i, v in pairs(node.children) do
if type(i) == "number" then
local newpath
if path ~= "" then
newpath = path.." @ "..v.name
else
newpath = v.name
end
self.paths[newpath] = v
v.mesh = nil
v.parent = node
node.children[v.name] = v
node.children[i] = nil
self:process_and_reformat(v, newpath)
end
end
if first then
for i, v in pairs(self.paths) do
print(i)
print(table.tostring(v.rotation))
print(table.tostring(v.position))
print(table.tostring(v.scale))
end
end
end

View File

@ -47,7 +47,9 @@ function player_model:update()
player:set_bone_position("guns3d_reticle_bone", eye_pos, vector.new(combined.x, 180-combined.y, 0))
player:set_bone_position("guns3d_head", self.offsets.head, {x=pitch,z=0,y=0})
local rot = vector.dir_to_rotation(gun.paxial_dir)*180/math.pi
--can't use paxial dir as it needs to be relative on Y still.
local dir = vector.rotate(gun.local_paxial_dir, {x=gun.offsets.player_rotation.x*math.pi/180,y=0,z=0})
local rot = vector.dir_to_rotation(dir)*180/math.pi
player:set_bone_position("guns3d_aiming_bone", eye_pos, {x=rot.x,y=-rot.y+180,z=0})
end
function player_model:prepare_deletion()

View File

@ -1,2 +0,0 @@
player_api
modlib

View File

@ -1,2 +1,3 @@
when spamming on_use, sometimes RMB in get_player_control will become stuck
when aim >75 <-75 it gets wonky, no idea how this happens, seemingly defies laws of math.
when spamming on_use, sometimes RMB in get_player_control will become stuck (engine)
classes that pollute global environment: Sprite_scope, Bullet_ray, Sprite_scope

View File

@ -2,26 +2,23 @@
VFX, SFX:
Bullet hit node FX (steal mostly from 3dguns)
~Bullet hit node FX (steal mostly from 3dguns)
Bullet fly-by SFX
HUD system (most can once again be pulled from 3dguns)
reload progress
ammunition left
ammo type
gun animations (take 3dguns as an example, then completely rewrite)
+player model & gun model reading
player model & gun model reading
gun sounds
gun features
firemodes
gun ammo:
~magazine relaoding
fractional reloading
magless flat reload
*!!fix gimbal lock (ironsights broken)*
"3d" optics
attachments (last before beta)
fix shooting through walls be pressing against them
fix shooting through walls while pressing against them
correct player look-down
gun leaning
add hip and aim bone offsets (this is for guns or modifiers that add stuff like "laser sights" or hud that simulates holographic sights, could be cool for futuristic type shooters)
@ -33,8 +30,9 @@ bullets
on_hitnode function callback
compatibility
add consts for player inv use in Ammo_handler
make monoid for player properties, player look offsets (especially needed for vehicle mods)
add consts for player inv use in Ammo_handler (i.e. "main", "craft_inv")
make monoid or use for player properties, player look offsets (especially needed for vehicle mods)
possibly make a library for overriding core functions.
optimization
hardcore optimization of get_dir() type functions required- super inefficient.

View File

@ -1,6 +1,7 @@
local Vec = vector
Guns4d = {
players = {}
players = {},
gun_by_ObjRef = {} --used for getting the gun object by the ObjRef of the gun
}
local path = minetest.get_modpath("guns4d")
dofile(path.."/misc_helpers.lua")
@ -10,6 +11,7 @@ dofile(path.."/block_values.lua")
dofile(path.."/register_ammo.lua")
path = path .. "/classes"
dofile(path.."/Instantiatable_class.lua")
dofile(path.."/Model_reader.lua")
dofile(path.."/Bullet_ray.lua")
dofile(path.."/Control_handler.lua")
dofile(path.."/Ammo_handler.lua")
@ -19,19 +21,50 @@ dofile(path.."/Player_model_handler.lua")
dofile(path.."/Player_handler.lua")
dofile(path.."/Proxy_table.lua")
Guns4d.Model_bone_handler:new({modelpath="model_reader_test.b3d"})
--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] = {
handler = player_handler:new({player=player})
}
player:set_fov(80)
end)
if not objref_mtable then
objref_mtable = getmetatable(player)
--putting this here is hacky as fuck.
local old_get_pos = objref_mtable.get_pos
function objref_mtable.get_pos(self)
local gun = Guns4d.gun_by_ObjRef[self]
if not gun then
return old_get_pos(self)
else
local v, _, _ = gun:get_pos()
return v
end
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
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].handler:prepare_deletion()

5
mod.conf Normal file
View File

@ -0,0 +1,5 @@
name = guns4d
title = guns4d
description = Adds a library for 3d guns
author = FatalError42O
depends = mtul_b3d

View File

Binary file not shown.

1
test.gltf Normal file

File diff suppressed because one or more lines are too long

View File

@ -148,7 +148,6 @@ minetest.register_entity("guns4d:bullet_hole", {
if self.timer < 30 then
if self.timer < 0 then
self.object:remove()
minetest.chat_send_all("removed")
return
end
local properties = self.object:get_properties()