Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion gamedata/configs/2_guide_on_adding_to_new_anim_sets.ltx
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,28 @@ And thats it! it should be working once you relaunch the game
ADDING NEW MAGAZINE MODELs:
preferably, you should try to align the mag models and their bones so they all line up
Then add the sections and models associated to the "scripted_magazines.script"'s "mag_models" table
Thats it ! But remember to actually make them appear you need to do the above
Thats it ! But remember to actually make them appear you need to do the above
PER-MAG COORDINATES (optional, backward compatible):
By default every mag on a gun uses the same shared offset (s_magazine_positions_[BONE], etc).
If a particular mag model has a different pivot / size and needs its own offset, add a key
suffixed with that magazine's SECTION name:
s_magazine_positions_[BONE]_[MAG_SECTION] = x,y,z
s_magazine_rotations_[BONE]_[MAG_SECTION] = x,y,z
s_magazine_scale_[BONE]_[MAG_SECTION] = float
s_magazine_parent_bone_[BONE]_[MAG_SECTION] = [bone]
[MAG_SECTION] is the loaded magazine item section, e.g. mag_ak_5.45x39_extended.
Resolution per field: if the suffixed key exists it is used, otherwise the script falls back
to the shared s_magazine_..._[BONE] key. So guns that only define the shared keys keep working
exactly as before - the shared coords are applied to every mag on that gun.

Example (bone "magazin", standard mag uses shared coords, the longer 45-round mag overrides):
![wpn_ak74]
s_magazine_hide_bones = magazin
s_magazine_parent_bone_magazin = magazin
; shared / fallback (used by the standard mag and any unlisted mag):
s_magazine_positions_magazin = 0,0,0
s_magazine_rotations_magazin = 0,0,0
s_magazine_scale_magazin = 1
; per-mag override for the extended mag only:
s_magazine_positions_magazin_mag_ak_5.45x39_extended = 0,-0.01,0
s_magazine_scale_magazin_mag_ak_5.45x39_extended = 1
78 changes: 65 additions & 13 deletions gamedata/scripts/scripted_magazines.script
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,11 @@ function change_specific_mag_model(configs)
-- this function returns an id
local parent_bone = string.sub(name, 10)
if parent_bone == bone_to_switch then
attachment:set_model(model_path, false)
-- only swap the model when it actually changed (see update_scripted_magazines):
-- re-setting a live attachment's model resets its transform for a frame
if attachment:get_model() ~= model_path then
attachment:set_model(model_path, false)
end

-- bullet swapping behaviour
local configs2 = {}
Expand All @@ -219,7 +223,29 @@ function change_specific_mag_model(configs)
add_bullets_to_magazines(obj, configs2)
-- bullet swapping behaviour

local scale = ini_sys:r_float_ex(obj_sec, "s_magazine_scale_" .. parent_bone) or 1
-- per-mag offsets (mirrors update_scripted_magazines): prefer the mag-suffixed
-- key so the swapped model lands on its FINAL position/rotation/scale immediately.
-- Without setting position/rotation here the model swaps but keeps the previous
-- mag's pose until the next idle refresh - visibly wrong mid-reload.
local swap_sec = configs2.section
local function swap_key(prefix)
local base = prefix .. parent_bone
if swap_sec and ini_sys:r_string_ex(obj_sec, base .. "_" .. swap_sec) then
return base .. "_" .. swap_sec
end
return base
end

local positions = str_explode(ini_sys:r_string_ex(obj_sec, swap_key("s_magazine_positions_")) or "", ",")
for i,v in pairs(positions) do positions[i] = tonumber(v) end

local rotations = str_explode(ini_sys:r_string_ex(obj_sec, swap_key("s_magazine_rotations_")) or "", ",")
for i,v in pairs(rotations) do rotations[i] = tonumber(v) end

local scale = ini_sys:r_float_ex(obj_sec, swap_key("s_magazine_scale_")) or 1

attachment:set_position(positions[1], positions[2], positions[3])
attachment:set_rotation(rotations[1], rotations[2], rotations[3])
attachment:set_scale(scale)
end
dbg("obj %s, bone_to_switch %s, model_path %s, name %s parent_bone %s", obj:name(), bone_to_switch, model_path, name, parent_bone)
Expand Down Expand Up @@ -268,8 +294,12 @@ function update_scripted_magazines(obj, configs)
attachment:set_scale(0)
end
end
if configs.hide_override then
-- basically hide_override is true if the gun is doing an animation that ISNT reload. So if the gun is reloading we wont hide the magazine bone
-- basically hide_override is true if the gun is doing an animation that ISNT reload. So if the gun is reloading we wont hide the magazine bone
-- ...and not while a Mags Reloaded reload is still in progress: at reload end the
-- idle anim can trigger this refresh BEFORE the new mag data commits (same frame),
-- and scaling the attachment to 0 in that window hides the freshly inserted mag
-- until the next anim change (movement)
if configs.hide_override and not (magazines.action_in_progress and magazines.action_in_progress()) then
obj:iterate_attachments(iterator)
end

Expand Down Expand Up @@ -299,6 +329,23 @@ function update_scripted_magazines(obj, configs)

-- iterates through each mag bone, not really necessary i just thought it would be useful when i first made it
configs.skip_bone_name = configs.skip_bone_name or {}

-- PER-MAG OFFSETS (backward compatible): for each offset field, prefer a key suffixed
-- with the magazine's section ("s_magazine_<field>_<bone>_<mag_section>") and fall back
-- to the shared per-bone key ("s_magazine_<field>_<bone>"). Guns that only define the
-- shared keys are unaffected. The loaded mag is authoritative; during the mid-reload
-- swap it is still nil/old, so we fall back to the incoming/pending section dev already
-- captures, so the model lands on its final coords immediately instead of jumping.
local loaded_mag = get_mag_loaded(obj:id())
local mag_section = (loaded_mag and loaded_mag.section) or incoming_mag_section or pending_swap_mag_section
local function mag_key(prefix, name)
local base = prefix .. name
if mag_section and ini_sys:r_string_ex(obj_section, base .. "_" .. mag_section) then
return base .. "_" .. mag_section
end
return base
end

for i,name in pairs(mag_bone_names) do
if configs.skip_bone_name[name] then goto continue end

Expand All @@ -314,28 +361,33 @@ function update_scripted_magazines(obj, configs)

-- add_attachment can fail
if not s_magazine then goto continue end

s_magazine:set_model(magazine_model_path, false)

-- only swap the model when it actually changed: set_model on a live attachment
-- resets its transform until the setters below re-apply, rendering one frame at
-- the default pose
if s_magazine:get_model() ~= magazine_model_path then
s_magazine:set_model(magazine_model_path, false)
end

-- finds positions
local positions = ini_sys:r_string_ex(obj_section, "s_magazine_positions_" .. name) or ""
local positions = ini_sys:r_string_ex(obj_section, mag_key("s_magazine_positions_", name)) or ""
positions = str_explode(positions, ",")
for i,v in pairs(positions) do
positions[i] = tonumber(v)
end

-- finds rotations
local rotations = ini_sys:r_string_ex(obj_section, "s_magazine_rotations_" .. name) or ""
local rotations = ini_sys:r_string_ex(obj_section, mag_key("s_magazine_rotations_", name)) or ""
rotations = str_explode(rotations, ",")
for i,v in pairs(rotations) do
rotations[i] = tonumber(v)
end

-- finds scale
local scale = ini_sys:r_float_ex(obj_section, "s_magazine_scale_" .. name) or 1
local scale = ini_sys:r_float_ex(obj_section, mag_key("s_magazine_scale_", name)) or 1

-- finds parent bone
local parent_bone = ini_sys:r_string_ex(obj_section, "s_magazine_parent_bone_" .. name) or "wpn_body"
local parent_bone = ini_sys:r_string_ex(obj_section, mag_key("s_magazine_parent_bone_", name)) or "wpn_body"

-- sets everything necessary
s_magazine:set_type(script_attachment_type.Hud)
Expand Down