update from MTUL to LEEF

This commit is contained in:
FatalErr42O 2024-12-01 16:19:51 -08:00
parent 6e62d56e23
commit 9990c92309
20 changed files with 128 additions and 125 deletions

View File

@ -5,6 +5,6 @@
"dump",
"player_api",
"ItemStack",
"mtul"
"leef"
]
}

View File

@ -96,15 +96,15 @@
( ) (for 5.9) make infinite ammo priv to rely on on_grant and on_revoke callback for runtime changes (cannot be done as broken in 5.8)
( ) (5.9) POTENTIALLY make models use new PR that allows bone offsets to be disabled
-I'd probably have to modify models at loadtime to have an eye and hipfire bone? Probably easier then current system though.
(x) Fix HORRIBLE namespace violation in misc_helpers.lua. Also migrate features to MTUL libraries
(x) Fix HORRIBLE namespace violation in misc_helpers.lua. Also migrate features to leef libraries
MTUL subtasks
( ) make ObjRef method override stuff MTUL and not 4dguns
leef subtasks
( ) make ObjRef method override stuff leef and not 4dguns
this won't be fun.
documentation
( ) mtul.class.new_class
( ) leef.class.new_class
( ) Player_model_handler
( ) Registering a model for compatibility

View File

@ -10,4 +10,4 @@ end
function attachment:update_entity()
self.entity = nil
end
Guns4d.gun_attachment = mtul.class.new_class:inherit(attachment)
Guns4d.gun_attachment = leef.class.new_class:inherit(attachment)

View File

@ -1,4 +1,4 @@
local Ammo_handler = mtul.class.new_class:inherit({
local Ammo_handler = leef.class.new_class:inherit({
name = "Ammo_handler",
construct = function(def)
if def.instance then
@ -67,14 +67,14 @@ end
function Ammo_handler:get_magazine_bone_info()
local gun = self.gun
local handler = self.gun.handler
local node = mtul.b3d_nodes.get_node_by_name(gun.b3d_model, gun.properties.visuals.magazine, true)
local node = leef.b3d_nodes.get_node_by_name(gun.b3d_model, gun.properties.visuals.magazine, true)
--get trans of first frame
if not node then
minetest.log("error", "improperly set gun magazine bone name, could not properly calculate magazine transformation.")
return self.gun.pos, vector.new(), vector.new()
end
local pos1 = vector.new(mtul.b3d_nodes.get_node_global_position(nil, node, true, math.floor(gun.animation_data.current_frame)))
local pos2 = vector.new(mtul.b3d_nodes.get_node_global_position(nil, node, true, gun.animation_data.current_frame))
local pos1 = vector.new(leef.b3d_nodes.get_node_global_position(nil, node, true, math.floor(gun.animation_data.current_frame)))
local pos2 = vector.new(leef.b3d_nodes.get_node_global_position(nil, node, true, gun.animation_data.current_frame))
local vel = (pos2-pos1)*((gun.animation_data.current_frame-math.floor(gun.animation_data.current_frame))/gun.animation_data.fps)+self.gun.player:get_velocity()
local pos = self.gun:get_pos(pos2*gun.properties.visual_scale)+self.gun.handler:get_pos()
--[[so I tried to get the rotation before, and it actually turns out that was... insanely difficult? Why? I don't know, the rotation behavior was beyond unexpected, I tried implementing it with quats and

View File

@ -1,5 +1,5 @@
--will have to merge with ammo_handler eventually for coherency.
local attachment_handler = mtul.class.new_class:inherit({})
local attachment_handler = leef.class.new_class:inherit({})
Guns4d.attachment_handler = attachment_handler
function attachment_handler:construct()
assert(self.gun, "no gun object provided")
@ -68,11 +68,11 @@ function attachment_handler:can_add(itemstack, slot)
assert(self.instance)
local name = itemstack:get_name()
local props = self.gun.properties
print(slot, dump(self.attachments))
--print(slot, dump(self.attachments))
if Guns4d.registered_attachments[name] and (not self.attachments[slot][name]) and (props.inventory.attachment_slots[slot].allowed) then
--check if it's allowed, group check required
for i, v in pairs(props.inventory.attachment_slots[slot].allowed) do
print(v, name)
--print(v, name)
if v==name then
return true
end

View File

@ -35,7 +35,7 @@ minetest.register_globalstep(function(dt)
end
end
end)
Guns4d.bullet_hole = mtul.class.new_class:inherit({
Guns4d.bullet_hole = leef.class.new_class:inherit({
texture = 'bullet_hole.png',
exp_time = 30, --how much time a rendered bullet hole takes to expire
unrendered_exptime = 10, --how much time an unrendered bullet hole takes to expire

View File

@ -445,4 +445,4 @@ function ray.construct(def)
end
end
end
Guns4d.bullet_ray = mtul.class.new_class:inherit(ray)
Guns4d.bullet_ray = leef.class.new_class:inherit(ray)

View File

@ -185,4 +185,4 @@ function controls.construct(def)
end)
end
end
Guns4d.control_handler = mtul.class.new_class:inherit(Guns4d.control_handler)
Guns4d.control_handler = leef.class.new_class:inherit(Guns4d.control_handler)

View File

@ -1,4 +1,4 @@
local Dynamic_crosshair = mtul.class.new_class:inherit({
local Dynamic_crosshair = leef.class.new_class:inherit({
increments = 1, --the number of pixels the reticle moves per frame.
frames = 32, --this defines the length of the sprite sheet. But it also helps us know how wide it is (since we have increments.)
image = "dynamic_crosshair_circular.png",

View File

@ -157,7 +157,7 @@ local function validate_controls(props)
end
end
local function initialize_b3d_animation_data(self, props)
self.b3d_model = mtul.b3d_reader.read_model(props.visuals.mesh)
self.b3d_model = leef.b3d_reader.read_model(props.visuals.mesh)
self.b3d_model.global_frames = {
arm_right = {}, --the aim position of the right arm
arm_left = {}, --the aim position of the left arm
@ -165,20 +165,20 @@ local function initialize_b3d_animation_data(self, props)
}
--print(table.tostring(self.b3d_model))
--precalculate keyframe "samples" for intepolation.
local left = mtul.b3d_nodes.get_node_by_name(self.b3d_model, self.consts.ARM_LEFT_BONE, true)
local right = mtul.b3d_nodes.get_node_by_name(self.b3d_model, self.consts.ARM_RIGHT_BONE, true)
local main = mtul.b3d_nodes.get_node_by_name(self.b3d_model, self.consts.ROOT_BONE, true)
--we add 2 because we have to add 1 for the loop to make it there if it's a float val, and MTUL uses a system where frame 0 is 1
local left = leef.b3d_nodes.get_node_by_name(self.b3d_model, self.consts.ARM_LEFT_BONE, true)
local right = leef.b3d_nodes.get_node_by_name(self.b3d_model, self.consts.ARM_RIGHT_BONE, true)
local main = assert(leef.b3d_nodes.get_node_by_name(self.b3d_model, self.consts.ROOT_BONE, true), "gun root-bone for "..self.itemstring.." not present in model")
--we add 2 because we have to add 1 for the loop to make it there if it's a float val, and leef uses a system where frame 0 is 1
for target_frame = 0, self.b3d_model.node.animation.frames+1, self.consts.KEYFRAME_SAMPLE_PRECISION do
--we need to check that the bone exists first.
if left then
table.insert(self.b3d_model.global_frames.arm_left, vector.new(mtul.b3d_nodes.get_node_global_position(self.b3d_model, left, nil, target_frame))*props.visuals.scale)
table.insert(self.b3d_model.global_frames.arm_left, vector.new(leef.b3d_nodes.get_node_global_position(self.b3d_model, left, nil, target_frame))*props.visuals.scale)
else
self.b3d_model.global_frames.arm_left = nil
end
if right then
table.insert(self.b3d_model.global_frames.arm_right, vector.new(mtul.b3d_nodes.get_node_global_position(self.b3d_model, right, nil, target_frame))*props.visuals.scale)
table.insert(self.b3d_model.global_frames.arm_right, vector.new(leef.b3d_nodes.get_node_global_position(self.b3d_model, right, nil, target_frame))*props.visuals.scale)
else
self.b3d_model.global_frames.arm_right = nil
end
@ -187,7 +187,8 @@ local function initialize_b3d_animation_data(self, props)
--ATTENTION: this is broken, roll is somehow translating to yaw. How? fuck if I know, but I will have to fix this eventually.
--use -1 as it does not exist and thus will always go to the default resting pose
--we compose it by the inverse because we need to get the global CHANGE in rotation for the animation rotation offset. I really need to comment more often
local newvec = (mtul.b3d_nodes.get_node_rotation(self.b3d_model, main, nil, -1):inverse())*mtul.b3d_nodes.get_node_rotation(self.b3d_model, main, nil, target_frame)
--print(leef.b3d_nodes.get_node_rotation(nil, main, nil, -1))
local newvec = leef.b3d_nodes.get_node_rotation(nil, main, nil, target_frame)*leef.b3d_nodes.get_node_rotation(nil, main, nil, -1):inverse()
--used to use euler
table.insert(self.b3d_model.global_frames.rotation, newvec)
end
@ -199,7 +200,7 @@ local function initialize_b3d_animation_data(self, props)
for i, v in pairs(self.b3d_model.node_paths) do
if v.mesh then
--if there's a mesh present transform it's verts into global coordinate system, add add them to them to a big list.
local transform, _ = mtul.b3d_nodes.get_node_global_transform(v, self.properties.visuals.animations.loaded.x, "transform")
local transform, _ = leef.b3d_nodes.get_node_global_transform(v, self.properties.visuals.animations.loaded.x, 1)
for _, vert in ipairs(v.mesh.vertices) do
vert.pos[4]=1
table.insert(verts, transform*vert.pos)
@ -299,7 +300,7 @@ function gun_default:construct_base_class()
for _, v in pairs(self.properties.ammo.accepted_magazines) do
self.accepted_magazines[v] = true
end
self.properties = mtul.class.proxy_table:new(self.properties)
self.properties = leef.class.proxy_table:new(self.properties)
Guns4d.gun._registered[self.name] = self --add gun self to the registered table
end

View File

@ -609,13 +609,13 @@ function gun_default:update_animation_rotation()
if self.b3d_model.global_frames.rotation then
if self.b3d_model.global_frames.rotation[frame1] then
if (not self.b3d_model.global_frames.rotation[frame2]) or (current_frame==frame1) then
out = vector.new(self.b3d_model.global_frames.rotation[frame1]:to_euler_angles_unpack())*180/math.pi
out = vector.new(self.b3d_model.global_frames.rotation[frame1]:get_euler_irrlicht_bone())*180/math.pi
--print("rawsent")
else --to stop nan
local ip_ratio = (current_frame-frame1)/(frame2-frame1)
local vec1 = self.b3d_model.global_frames.rotation[frame1]
local vec2 = self.b3d_model.global_frames.rotation[frame2]
out = vector.new(vec1:slerp(vec2, ip_ratio):to_euler_angles_unpack())*180/math.pi
out = vector.new(vec1:slerp(vec2, ip_ratio):get_euler_irrlicht_bone())*180/math.pi
end
else
out = vector.copy(self.b3d_model.global_frames.rotation[1])
@ -624,7 +624,8 @@ function gun_default:update_animation_rotation()
else
out = vector.new()
end
self.animation_rotation = out
--we use a different rotation system
self.animation_rotation = -out
end
--relative to the gun's entity. Returns left, right vectors.

View File

@ -528,4 +528,4 @@ gun_default.construct = function(def)
gun_default.construct_base_class(def)
end
end
Guns4d.gun = mtul.class.new_class:inherit(gun_default)
Guns4d.gun = leef.class.new_class:inherit(gun_default)

View File

@ -19,7 +19,7 @@ local function split_into_adresses(object, path, out)
end
return out
end
Modifier = mtul.class.new_class:inherit({
Modifier = leef.class.new_class:inherit({
overwrites = {},
construct = function(def)
if def.instance then

View File

@ -197,4 +197,4 @@ function player_handler.construct(def)
def.infinite_ammo = minetest.check_player_privs(def.player, Guns4d.config.infinite_ammo_priv)
end
end
Guns4d.player_handler = mtul.class.new_class:inherit(player_handler)
Guns4d.player_handler = leef.class.new_class:inherit(player_handler)

View File

@ -33,30 +33,26 @@ Guns4d.player_model_handler = {
--model generation attributes
override_bones = { --a list of bones to be read and or generated
__overfill = true,
Arm_Right = "guns4d_arm_right",
Arm_Left = "guns4d_arm_left",
Head = "guns4d_head"
},
new_bones = { --currently only supports empty bones. Sets at identity rotation, position 0, and parentless
"guns4d_gun_bone",
"guns4d_hipfire_bone"
},
bone_aliases = { --names of bones used by the model handler and other parts of guns4d.
__overfill = true,
arm_right = "guns4d_arm_right",
arm_right = "guns4d_arm_right", --this is a needed alias for hipfire position
arm_left = "guns4d_arm_left",
head = "guns4d_head",
gun = "guns4d_gun_bone",
gun = "guns4d_gun_bone", --another needed alias
},
still_frame = 0, --the frame to take bone offsets from. This system has to be improved in the future (to allow better animation support)- it works for now though.
auto_generate = true,
scale = 1, --this is important for autogen
output_path = minetest.get_modpath("guns4d").."/temp/",
compatible_meshes = { --list of meshes and their corresponding partner meshes for this handler. Must have the same bones used by guns4d.
compatible_meshes = { --list of meshes and their corresponding partner meshes for this handler. Must have the same bones used by guns4d. The first on this list will be read and have it's bone offsets logged for use.
--["character.b3d"] = "guns4d_character.b3d", this would tell the handler to use guns4d_character.b3d instead of generating a new one based on the override parameters.
["character.b3d"] = (mtul.paths.media_paths["character.b3d"] and true) or nil, --it is compatible but it has no predefined model, one will be therefore generated using the override_bone_aliases parameters.
__overfill = true
["character.b3d"] = (leef.paths.media_paths["character.b3d"] and true) or nil, --it is compatible but it has no predefined model, one will be therefore generated using the override_bone_aliases parameters.
},
gun_bone_location = vector.new(),
fallback_mesh = "character.b3d", --if no meshes are found in "compatible_meshes" it chooses this index in "compatible_meshes"
@ -76,12 +72,12 @@ function player_model.get_handler(meshname)
return player_model.default_handler
end
function player_model:add_compatible_mesh(original, replacement)
--[[function player_model:add_compatible_mesh(original, replacement)
assert(not self.instance, "attempt to call class method on an object. Cannot modify original class from an instance.")
assert(original and replacement, "one or more parameters missing")
self.compatible_meshes[original] = replacement
player_model.handlers[original] = self
end
end]]
--we store the read file so it can be reused in the constructor if needed.
local model_buffer
@ -90,64 +86,67 @@ function player_model:custom_b3d_generation_parameters(b3d)
--empty for now, this is for model customizations.
return b3d
end
function player_model:replace_b3d_bone(b3d)
end
--generates a new guns4d model bases off of the `new_bones` and `bone_overrides` parameters if one does not already exist.
function player_model:generate_b3d_model(name)
assert(self and name, "error while generating a b3d model. Name not provided or not called as a method.")
if not mtul.paths.media_paths[name.b3d] then
--generate a new model
local filename = string.sub(name, 1, -5).."_guns4d_temp.b3d"
local new_path = self.output_path..filename
--generate a new model
local filename = string.sub(name, 1, -5).."_guns4d_temp.b3d"
local new_path = self.output_path..filename
--buffer and modify the model
model_buffer = mtul.b3d_reader.read_model(name)
local b3d = model_buffer
local replaced = {}
--add bone... forgot i made this so simple by adding node_paths
for _, node in pairs(b3d.node_paths) do
if self.override_bones[node.name] then
replaced[node.name] = true
--change the name
node.name = self.override_bones[node.name]
--unset rotation because it breaks shit
local rot = node.rotation
for i, v in pairs(node.keys) do
v.rotation = rot
end
--node.rotation = {0,0,0,1}
--buffer and modify the model
model_buffer = leef.b3d_reader.read_model(name)
local b3d = model_buffer
local replaced = {}
--add bone... forgot i made this so simple by adding node_paths
for _, node in pairs(b3d.node_paths) do
if self.override_bones[node.name] then
replaced[node.name] = true
--change the name
node.name = self.override_bones[node.name]
--unset rotation because it breaks shit
local rot = node.rotation
for i, v in pairs(node.keys) do
v.rotation = rot
end
--node.rotation = {0,0,0,1}
end
--check bones were replaced to avoid errors.
for i, v in pairs(self.override_bones) do
if (not replaced[i]) and i~="__overfill" then
error("bone '"..i.."' not replaced with it's guns4d counterpart, bone was not found. Check bone name")
end
end
for i, v in pairs(self.new_bones) do
table.insert(b3d.node.children, {
name = v,
position = {0,0,0},
scale = {1/self.scale,1/self.scale,1/self.scale},
rotation = {0,0,0,1},
children = {},
bone = {} --empty works?
})
end
b3d=self:custom_b3d_generation_parameters(b3d)
--write temp model
local writefile = io.open(new_path, "w+b")
mtul.b3d_writer.write_model_to_file(b3d, writefile)
writefile:close()
--send to player media paths
minetest.after(0, function()
assert(
minetest.dynamic_add_media({filepath = new_path}, function()end),
"failed sending media"
)
end)
mtul.paths.media_paths[filename] = new_path
mtul.paths.modname_by_media[filename] = "guns4d"
return filename
end
--check bones were replaced to avoid errors.
for i, v in pairs(self.override_bones) do
if (not replaced[i]) and i~="__overfill" then
error("bone '"..i.."' not replaced with it's guns4d counterpart, bone was not found. Check bone name")
end
end
for i, v in pairs(self.new_bones) do
table.insert(b3d.node.children, {
name = v,
position = {0,0,0},
scale = {1/self.scale,1/self.scale,1/self.scale},
rotation = {0,0,0,1},
children = {},
bone = {} --empty works?
})
end
--call custom generation parameters...
b3d=self:custom_b3d_generation_parameters(b3d)
--write temp model
local writefile = io.open(new_path, "w+b")
leef.b3d_writer.write_model_to_file(b3d, writefile)
writefile:close()
--send to player media paths
minetest.after(0, function()
assert(
minetest.dynamic_add_media({filepath = new_path}, function()end),
"failed sending media"
)
end)
leef.paths.media_paths[filename] = new_path
leef.paths.modname_by_media[filename] = "guns4d"
return filename
end
-- main update function
@ -184,10 +183,12 @@ function player_model:update_aiming(dt)
{
position = {
vec={x=pos.x, y=pos.y, z=pos.z},
absolute = true
absolute = true,
interpolation=.25
},
rotation = {
vec={x=-rot.x,y=-rot.y,z=0},
interpolation=.1,
absolute = true
}
})
@ -197,6 +198,7 @@ function player_model:update_aiming(dt)
-- minetest.chat_send_all(dump(pos))
end
--default arm code, compatible with MTG model.
function player_model:update_arm_bones(dt)
local player = self.player
local handler = self.handler
@ -226,7 +228,7 @@ function player_model:update_arm_bones(dt)
}
})
end
--updates the rotation of the head to match the gun.
function player_model:update_head(dt)
local player = self.player
local handler = self.handler
@ -272,15 +274,9 @@ function player_model.construct(def)
def.handler:set_properties(properties)
--no further aciton required, it e
-- character.b3d (from player_api) not present, ignore generation.
elseif (def~=player_model) or mtul.paths.media_paths["character.b3d"] then
--none of these should consist across classes
def.offsets = {
global = {},
relative = {},
}
--a list of meshes compatible with this handler.
elseif (def~=player_model) or (minetest.get_modpath("player_api")) then
for og_mesh, replacement_mesh in pairs(def.compatible_meshes) do
assert(type(og_mesh)=="string", "mesh to be replaced (index) must be a string!")
assert(type(og_mesh)=="string", "mesh index to be replaced in compatible_meshes must be a string!")
if player_model.handlers[og_mesh] then minetest.log("warning", "Guns4d: mesh '"..og_mesh.."' overridden by a handler class, this will replace the old handler. Is this a mistake?") end
player_model.handlers[replacement_mesh] = def
end
@ -292,35 +288,40 @@ function player_model.construct(def)
end
local read_model
for i, v in pairs(def.compatible_meshes) do
if (type(i)=="string") and (i~="__overfill") then
if def.auto_generate and ((not v) or not mtul.paths.media_paths[v]) then
def.compatible_meshes[i] = def:generate_b3d_model(i)
if type(i)=="string" then
if (v==true) then
if def.auto_generate then
def.compatible_meshes[i] = def:generate_b3d_model(i)
elseif i~=def.fallback_mesh then
def.compatible_meshes[i] = def.compatible_meshes[def.fallback_mesh]
else
error("improperly set list of compatible_meshes in a player_model_handler inherited class. Fallback mesh "..def.fallback_mesh.." has no assigned mesh and auto_generate is off")
end
end
read_model=def.compatible_meshes[i]
end
end
minetest.log(read_model, "at least one compatible mesh required by default for autogeneration of offsets")
local b3d_table = mtul.b3d_reader.read_model(read_model, true)
assert(read_model, "at least one compatible mesh required by default for autogeneration of offsets")
local b3d_table = leef.b3d_reader.read_model(read_model, true)
--[[all of the compatible_meshes should be identical in terms of guns4d specific bones and offsets (arms, head).
Otherwise a new handler should be different. With new compatibilities]]
for i, v in pairs(def.bone_aliases) do
--print(def.bone_aliases[v])
local node = mtul.b3d_nodes.get_node_by_name(b3d_table, v, true)
if i~="__overfill" then
local transform, _ = mtul.b3d_nodes.get_node_global_transform(node, def.still_frame)
print(def.bone_aliases[i])
local node = leef.b3d_nodes.get_node_by_name(b3d_table, v, true)
assert(node, "player model handler: no node found by the name of \""..v.."\" check that it is the correct value, or that it has been correctly overriden to use that name.")
local transform, _ = leef.b3d_nodes.get_node_global_transform(node, def.still_frame)
def.offsets.relative[i] = vector.new(node.position[1], node.position[2], node.position[3])
def.offsets.global[i] = vector.new(transform[13], transform[14], transform[15])/10 --4th column first 3 rows give us our global transform.
--print(i, mtul.b3d_nodes.get_node_rotation(b3d_table, node, true, def.still_frame))
end
def.offsets.relative[i] = vector.new(node.position[1], node.position[2], node.position[3])
def.offsets.global[i] = vector.new(transform[13], transform[14], transform[15])/10 --4th column first 3 rows give us our global transform.
--print(i, leef.b3d_nodes.get_node_rotation(b3d_table, node, true, def.still_frame))
end
def.offsets.global.hipfire = vector.new(mtul.b3d_nodes.get_node_global_position(b3d_table, def.bone_aliases.arm_right, true, def.still_frame))
def.offsets.global.hipfire = vector.new(leef.b3d_nodes.get_node_global_position(b3d_table, def.bone_aliases.arm_right, true, def.still_frame))
if def.is_new_default then
player_model.set_default_handler(def)
end
end
end
Guns4d.player_model_handler = mtul.class.new_class:inherit(player_model)
Guns4d.player_model_handler = leef.class.new_class:inherit(player_model)
Guns4d.player_model_handler:set_default_handler()

View File

@ -1,4 +1,4 @@
local Sprite_scope = mtul.class.new_class:inherit({
local Sprite_scope = leef.class.new_class:inherit({
images = {
fore = {
texture = "scope_fore.png",

View File

@ -148,7 +148,7 @@ minetest.register_on_joinplayer(function(player)
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)
--ObjRef overrides will be integrated into leef (eventually TM)
if not objref_mtable then
objref_mtable = getmetatable(player)

View File

@ -2,5 +2,5 @@ name = guns4d
title = guns4d
description = Adds a library for 3d guns
author = FatalError42O
depends = mtul_b3d, mtul_cpml, mtul_filesystem, mtul_class
depends = leef_b3d, leef_math, leef_filesystem, leef_class
optional_depends = spriteguns, sprint

View File

@ -100,8 +100,8 @@ function Guns4d.play_sounds(soundspecs_list)
sound = Guns4d.math.weighted_randoms(sound)
end
assert(sound, "no sound provided")
if not mtul.paths.media_paths[(sound or "[NIL]")..".ogg"] then
minetest.log("error", "no sound by the name `"..mtul.paths.media_paths[(sound or "[NIL]")..".ogg"].."`")
if not leef.paths.media_paths[(sound or "[NIL]")..".ogg"] then
minetest.log("error", "no sound by the name `"..leef.paths.media_paths[(sound or "[NIL]")..".ogg"].."`")
end
local exclude_player_ref = soundspec.exclude_player
if type(soundspec.exclude_player)=="string" then

Binary file not shown.