Added New Mods and Profiles Folders

This is a complete rebuild of the modpack, with all new mods and updates for 1.5.3 of Anomaly.
This commit is contained in:
2025-01-14 05:07:53 -05:00
parent 85c665b107
commit 376b4b9689
21217 changed files with 546254 additions and 0 deletions
@@ -0,0 +1,120 @@
-- Might want to extend this to track flags based on IDs since detectors have animations too
-- Likely overkill unless someone implements custom anims for them
FLAGS = {}
local active_flags = {}
-- Export: Flags
function get_flag(flag)
return active_flags[flag]
end
function set_flag(flag)
active_flags[flag] = true
end
function remove_flag(flag)
active_flags[flag] = nil
end
function add_flag(flag)
-- Exit early if it already exists
if FLAGS[flag] then return end
FLAGS[flag] = #FLAGS
end
local anim_mutators = {}
-- Export: Animation Mutators
function add_anim_mutator(functor, priority)
-- Add mutator func to list of mutators
table.insert(anim_mutators, {functor=functor, priority=priority})
-- Sort anim_mutators again
table.sort(anim_mutators, function(a,b) return a.priority < b.priority end)
end
function has_animation(section, anm)
local hud_section = ini_sys:r_string_ex(section,"hud") or section
return SYS_GetParam(0, hud_section, anm)
end
function mutate_anim(anm_table, anm_suffix, section)
local new_anm = anm_table.anm_name .. anm_suffix
if has_animation(section, new_anm) then
anm_table.anm_name = new_anm
return true
end
return false
end
-- Sounds
local sound_object_by_sec_by_path = {}
function get_safe_sound_object(path, sec)
assert(path, "path to sound file was nil")
assert(sec, "item section was nil")
if sound_object_by_sec_by_path[sec] == nil then
sound_object_by_sec_by_path[sec] = {}
end
local snd_obj = sound_object(path)
sound_object_by_sec_by_path[sec][path] = snd_obj
return snd_obj
end
function stop_all_sound_object(sec)
-- printf("stop_all_sound_object(sec): %s", sec)
for section, list in pairs(sound_object_by_sec_by_path) do
for path, v in pairs(list) do
if section == sec and v:playing() then
-- printf("sec: %s| Stopping: %s", sec, path)
v:stop()
end
end
sound_object_by_sec_by_path[sec] = nil
end
end
function get_sound_from_anm(anm_name) -- TODO: allow sound volume to be defined in config
return anm_name:gsub("anm_", "scripted_snd_")
end
-- Probably worth adding an ordered list of functions with conditions that can mutate anm_table
-- and use this script as source of truth for about-to-be-played animations since callback order is random between scripts
function actor_on_hud_animation_play(anm_table, item)
if not item then return end
stop_all_sound_object(item:section())
local section = item:section()
-- Execute each mutator functor in turn, ordered by priority
for i, mutator in ipairs(anim_mutators) do
local stop = mutator.functor(anm_table, item)
if stop then break end
end
-- Sound: Check if weapon has a valid scripted sound in config
local anm_name = anm_table.anm_name
local snd_name = get_sound_from_anm(anm_name)
local snd_value = SYS_GetParam(0, section, snd_name)
if not snd_value then return end
local snd_values = str_explode(snd_value,",")
local snd_path = snd_values[1]
local never_cancel = snd_values[2]
-- Play sound
local snd_obj = get_safe_sound_object( snd_path, item:section() )
if not snd_obj then return end
if never_cancel then
snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0, 1.0)
else
snd_obj:play(db.actor, 0, sound_object.s2d)
end
end
function on_game_start()
RegisterScriptCallback("actor_on_hud_animation_play",actor_on_hud_animation_play)
end
@@ -0,0 +1,156 @@
--[[ New Extensible RF Sources
MCM initialization script
Author: Catspaw (CatspawMods @ ModDB)
Source: https://www.moddb.com/mods/stalker-anomaly/addons/new-extensible-rf-sources/
Tweaked for redistribution with Devices of Anomaly Redone
--]]
item_radio.load_me = function() end
ui_rf_widget.load_me = function() end
function on_mcm_load()
-- Trap if another addon has overwritten item_radio.script
local nerfs_installed = item_radio and item_radio.script_version
local dar_installed = (dar_rf_noise ~= nil)
local headerstring = nerfs_installed and "header" or "loadfailed"
local headercolor = nerfs_installed and {220,220,220,220} or {255,255,0,0}
local headerimg = dar_installed and "ui_mcm_nerfs_main_headerimg_new" or "ui_mcm_nerfs_main_headerimg"
op = { id= "nerfs", gr={
{ id = "nerfmain", sh=true, gr={
{id = "headerimg", type = "slide", link = headerimg, size = {512,235}, spacing = 0},
{id = "header1", type = "desc", clr = headercolor, text = "ui_mcm_nerfs_nerfmain_"..headerstring.."1"},
{id = "header2", type = "desc", clr = headercolor, text = "ui_mcm_nerfs_nerfmain_"..headerstring.."2"},
{id = "max_freq", type = "track", val = 2, min = 300, max = 999, step = 1, def = 300},
{id = "enable_rrfr", type = "check", val = 1, def = false},
{id = "use_mwheel", type = "check", val = 1, def = true},
{id = "binaries", type = "desc", text = "ui_mcm_nerfs_nerfmain_binaries"},
{id = "header3", type = "desc", text = "ui_mcm_nerfs_scrolldown"},
{id = "debuglogs", type = "check", val = 1, def = false},
},
},
{ id = "nerfpresets", sh=true, gr={
{id = "headerimg", type = "slide", link = "ui_mcm_nerfs_presets_headerimg", size = {512,50}, spacing = 20},
{id = "header1", type = "desc", clr = {255,255,255,0}, text = "ui_mcm_nerfpresets_header1"},
{id = "header2", type = "desc", clr = {255,200,200,200}, text = "ui_mcm_nerfpresets_header2"},
{id = "preset1_freq", type = "input", val = 2, min = 1, max = 999, def = 1},
{id = "kb_preset1", type = "key_bind", val = 2, def = DIK_keys.DIK_1},
{id = "mk_preset1", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset2_freq", type = "input", val = 2, min = 1, max = 999, def = 145},
{id = "kb_preset2", type = "key_bind", val = 2, def = DIK_keys.DIK_2},
{id = "mk_preset2", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset3_freq", type = "input", val = 2, min = 1, max = 999, def = 300},
{id = "kb_preset3", type = "key_bind", val = 2, def = DIK_keys.DIK_3},
{id = "mk_preset3", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset4_freq", type = "input", val = 2, min = 1, max = 999, def = 400},
{id = "kb_preset4", type = "key_bind", val = 2, def = DIK_keys.DIK_4},
{id = "mk_preset4", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset5_freq", type = "input", val = 2, min = 1, max = 999, def = 500},
{id = "kb_preset5", type = "key_bind", val = 2, def = DIK_keys.DIK_5},
{id = "mk_preset5", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset6_freq", type = "input", val = 2, min = 1, max = 999, def = 762},
{id = "kb_preset6", type = "key_bind", val = 2, def = DIK_keys.DIK_6},
{id = "mk_preset6", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset7_freq", type = "input", val = 2, min = 1, max = 999, def = 810},
{id = "kb_preset7", type = "key_bind", val = 2, def = DIK_keys.DIK_7},
{id = "mk_preset7", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset8_freq", type = "input", val = 2, min = 1, max = 999, def = 869},
{id = "kb_preset8", type = "key_bind", val = 2, def = DIK_keys.DIK_8},
{id = "mk_preset8", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{id = "preset9_freq", type = "input", val = 2, min = 1, max = 999, def = 915},
{id = "kb_preset9", type = "key_bind", val = 2, def = DIK_keys.DIK_9},
{id = "mk_preset9", type = ui_mcm.kb_mod_radio, val = 2, def = 3, hint = "mcm_kb_modifier",
content = {
{0,"mcm_kb_mod_none"},
{1,"mcm_kb_mod_shift"},
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
},
},
},
}
local widgetmenu =
{ id = "nerfwidget", sh=true, gr={
{id = "headerimg", type = "slide", link = "ui_mcm_nerfs_widget_headerimg", size = {512,288}, spacing = 20},
{id = "header", type = "desc", text = "ui_mcm_nerfs_nerfwidget_header1"},
{id = "show", type = "check", val = 1, def = false},
{id = "header", type = "desc", text = "ui_mcm_nerfs_nerfwidget_headerxy"},
{id = "pos_x", type = "input", val = 2, min = 0, max = 1024, def = 491},
{id = "pos_y", type = "input", val = 2, min = 0, max = 768, def = 670},
{id = "header", type = "desc", text = "ui_mcm_nerfs_scrolldown"},
{id = "header", type = "desc", text = "ui_mcm_nerfs_nerfwidget_lo_header"},
{id = "lo_a", type = "input", val = 2, min = 0, max = 255, def = 255, hint = "nerfs_nerfwidget_clr_a"},
{id = "lo_r", type = "input", val = 2, min = 0, max = 255, def = 50, hint = "nerfs_nerfwidget_clr_r"},
{id = "lo_g", type = "input", val = 2, min = 0, max = 255, def = 50, hint = "nerfs_nerfwidget_clr_g"},
{id = "lo_b", type = "input", val = 2, min = 0, max = 255, def = 50, hint = "nerfs_nerfwidget_clr_b"},
{id = "header", type = "desc", text = "ui_mcm_nerfs_nerfwidget_hi_header"},
{id = "hi_a", type = "input", val = 2, min = 0, max = 255, def = 255, hint = "nerfs_nerfwidget_clr_a"},
{id = "hi_r", type = "input", val = 2, min = 0, max = 255, def = 50, hint = "nerfs_nerfwidget_clr_r"},
{id = "hi_g", type = "input", val = 2, min = 0, max = 255, def = 250, hint = "nerfs_nerfwidget_clr_g"},
{id = "hi_b", type = "input", val = 2, min = 0, max = 255, def = 50, hint = "nerfs_nerfwidget_clr_b"},
{id = "header", type = "desc", text = "ui_mcm_nerfs_nerfwidget_em_header"},
{id = "em_a", type = "input", val = 2, min = 0, max = 255, def = 128, hint = "nerfs_nerfwidget_clr_a"},
{id = "em_r", type = "input", val = 2, min = 0, max = 255, def = 200, hint = "nerfs_nerfwidget_clr_r"},
{id = "em_g", type = "input", val = 2, min = 0, max = 255, def = 0, hint = "nerfs_nerfwidget_clr_g"},
{id = "em_b", type = "input", val = 2, min = 0, max = 255, def = 0, hint = "nerfs_nerfwidget_clr_b"},
},
}
if ui_rf_widget then
-- Add the accessibility widget menu if that script is present
table.insert(op.gr,widgetmenu)
end
return op
end
@@ -0,0 +1,31 @@
-- Removes background noise from the draw & holster of the RF-Receiver
local debuglogs = false
no_sound_states = {
anm_show = true,
anm_show_fast = true,
anm_hide_fast = true,
anm_hide = true,
}
sound_currently_enabled = false
function actor_on_hud_animation_play(anm_table, item)
if not item then return end
local parent_section = SYS_GetParam(0, item:section(), "parent_section", item:section())
if not (parent_section == "detector_radio") then return end
sound_currently_enabled = no_sound_states[anm_table.anm_name] == nil
if debuglogs then printf("<DAR> sound_currently_enabled %s | item section %s | anm_name %s",sound_currently_enabled, parent_section, anm_table and anm_table.anm_name) end
end
local has_valid_device = item_radio.actor_has_valid_device
function item_radio.actor_has_valid_device(mba)
local valid_dev = has_valid_device(mba)
if debuglogs then printf("<DAR> sound_currently_enabled is %s | valid device %s",sound_currently_enabled,valid_dev) end
return sound_currently_enabled and valid_dev
end
function on_game_start()
RegisterScriptCallback("actor_on_hud_animation_play", actor_on_hud_animation_play)
end
@@ -0,0 +1,28 @@
-- Out of Battery Draw Script
function actor_on_hud_animation_play(anm_table, item)
if not item then return end
if not animation_common.has_animation(item:section(), "anm_show_dead") then return end
if anm_table.anm_name == "anm_show" and item:condition() <= 0.05 then
anm_table.anm_name = "anm_show_dead"
end
end
function actor_on_update()
local actor = db.actor
local det = actor:active_detector()
if (det and string.find(det:section(), "flashlight")) then return end
zz_glowstick_mcm.actor_on_update()
end
function on_game_start()
RegisterScriptCallback("actor_on_hud_animation_play", actor_on_hud_animation_play)
if (zz_glowstick_mcm ~= nil) then
UnregisterScriptCallback("actor_on_update", zz_glowstick_mcm.actor_on_update)
RegisterScriptCallback("actor_on_update", actor_on_update)
end
end
@@ -0,0 +1,43 @@
-- Script by Utjan for Barry's Detector Remodel and Reanimations
-- Table of detectors to handle, and which light bones to toggle
valid_detectors = {
["detector_simple"] = {["light_bone_1"] = true, ["light_bone_3"] = true},
["detector_advanced"] = {["light_bone_1"] = true, ["light_bone_2"] = true, ["screen_bone_1"] = true, ["screen_bone"] = true},
["detector_elite"] = {["light_bone_1"] = true, ["light_bone_2"] = true, ["light_bone_3"] = true, ["light_bone_4"] = true, ["light_bone_5"] = true, ["light_bone_6"] = true, ["light_bone_7"] = true, ["light_bone_8"] = true, ["light_bone_9"] = true, ["cover_power"] = true},
["detector_scientific"] = {["light_bone_1"] = true, ["light_bone_2"] = true, ["light_bone_3"] = true, ["light_bone_4"] = true, ["light_bone_5"] = true, ["light_bone_6"] = true, ["light_bone_7"] = true, ["light_bone_8"] = true, ["light_bone_9"] = true, ["cover_power"] = true},
["detector_radio"] = {["light_bone"] = true, ["light_bone.001"] = true, ["screen_bone"] = true},
["detector_anomaly"] = {["light_bone_1"] = true},
["detector_geiger"] = {["cover"] = true},
["device_flashlight"] = {["light_bone_1"] = true},
}
function on_game_start()
RegisterScriptCallback("actor_on_update", actor_on_update)
end
function actor_on_update()
local active_device = db.actor:active_detector()
if not active_device then return end
if active_device:get_state() == 2 then return end -- Thank you Lucy and Aoldri for this fix
local det_bones = valid_detectors[active_device:section()] or nil
if not det_bones then return end
if active_device:condition() <= 0.05 then
for bone_name, v in pairs(det_bones) do
if active_device:bone_visible(bone_name, true) then
active_device:set_bone_visible(bone_name, false, false, true)
--printf("Hidden bone " .. bone_name)
end
end
else
for bone_name, v in pairs(det_bones) do
if not active_device:bone_visible(bone_name, true) then
active_device:set_bone_visible(bone_name, true, false, true)
---printf("Shown bone " .. bone_name)
end
end
end
end
@@ -0,0 +1,10 @@
if not z_beefs_nvgs then return end
function actor_on_first_update()
z_beefs_nvgs.mc_anm_time_1 = game.get_motion_length("anim_mask_clean", "anm_hide_hand", 1.5) -- hardcoded since they're local and don't change in script at all anyways
z_beefs_nvgs.torch_anm_time = game.get_motion_length("anim_headlamp", "anm_switch", 1)
end
function on_game_start()
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,107 @@
local dosimeter_ui = nil
local workIndicatorTimer = 0
local updateTimer = 0
local updateFreq = 555 -- in milliseconds
class "ui_dosimeter" (CUIScriptWnd)
function ui_dosimeter:__init() super()
self:Show (true)
self:Enable (true)
local xml = CScriptXmlInit()
self.xml = xml
xml:ParseFile ("ui_dosimeter.xml")
xml:InitWindow ("dosimeter", 0, self)
self.m_wrk_area = xml:InitStatic("dosimeter:wrk_area", self)
self.m_seg1 = xml:InitStatic("dosimeter:seg1", self)
self.m_seg2 = xml:InitStatic("dosimeter:seg2", self)
self.m_seg3 = xml:InitStatic("dosimeter:seg3", self)
self.m_seg4 = xml:InitStatic("dosimeter:seg4", self)
-- self.m_workIndicator = xml:InitStatic("dosimeter:work", self)
end
function ui_dosimeter:__finalize()
dosimeter_ui = nil
end
function ui_dosimeter:Update()
CUIScriptWnd.Update(self)
local tg = time_global()
-- if (tg > workIndicatorTimer + 1000) then
-- workIndicatorTimer = tg
-- self.m_workIndicator:Show(not self.m_workIndicator:IsShown())
-- end
if (tg < updateTimer) then
return
else
updateTimer = tg + updateFreq
end
local rads = item_device.dosimeter_env_rads_mode and math.floor(level.get_env_rads()*2500) or math.floor(db.actor.radiation*10000*0.387)
-- Emissions: the closer the wave, the higher the psi influnces
if GetEvent("surge", "state") then
local surge_time = GetEvent("surge", "time") or 0
local val_glitch = (surge_time > 168) and normalize(surge_time, 220, 168) or normalize(surge_time, 20, 168)
rads = (rads + 500) * math.random(0.5, 10) * clamp(val_glitch,0,1)
-- Psi-storms: huge spike when a vortex hits the ground
elseif GetEvent("psi_storm", "state") then
if GetEvent("psi_storm", "vortex") then
rads = (rads + 1000) * math.random(0.7, 1.3)
else
rads = rads * math.random(0.9, 1.1)
end
end
local s_rads = tostring(rads)
local seg1, seg2, seg3, seg4
if (rads > 999) then
seg1 = strformat("green_%s", s_rads:sub(1, 1))
seg2 = strformat("green_%s", s_rads:sub(2, 2))
seg3 = strformat("green_%s", s_rads:sub(3, 3))
seg4 = strformat("green_%s", s_rads:sub(4, 4))
elseif (rads > 99) then
seg1 = "green_0"
seg2 = strformat("green_%s", s_rads:sub(1, 1))
seg3 = strformat("green_%s", s_rads:sub(2, 2))
seg4 = strformat("green_%s", s_rads:sub(3, 3))
elseif (rads > 9) then
seg1 = "green_0"
seg2 = "green_0"
seg3 = strformat("green_%s", s_rads:sub(1, 1))
seg4 = strformat("green_%s", s_rads:sub(2, 2))
elseif (rads > 0) then
seg1 = "green_0"
seg2 = "green_0"
seg3 = "green_0"
seg4 = strformat("green_%s", s_rads:sub(1, 1))
else
seg1 = "green_0"
seg2 = "green_0"
seg3 = "green_0"
seg4 = "green_0"
end
self.m_seg1:InitTextureEx(seg1, "hud\\p3d")
self.m_seg2:InitTextureEx(seg2, "hud\\p3d")
self.m_seg3:InitTextureEx(seg3, "hud\\p3d")
self.m_seg4:InitTextureEx(seg4, "hud\\p3d")
end
function get_UI()
if(dosimeter_ui==nil) then
dosimeter_ui = ui_dosimeter()
end
return dosimeter_ui
end
@@ -0,0 +1,116 @@
-- ======================================================================
--[[ RF accessibility widget
Author: Catspaw
Credits: based on code by RavenAscendant
-- ======================================================================
This file is required for the RF receiver accessibility widget
included with NERFS.
It takes no action of its own unless called, and will not conflict
with anything whatsoever--but if you don't need it, you can safely
delete this file without any ill effects to NERFS.
-- ===================================================================--]]
class "UIRFWidget" (CUIScriptWnd)
function UIRFWidget:__init(xmlfile,element,texture,pos) super()
self:InitControls(xmlfile,element,texture,pos)
RegisterScriptCallback("actor_on_net_destroy", self)
end
function UIRFWidget:__finalize()
end
function UIRFWidget:InitControls(xmlfile,element,texture,pos)
self.colors = {
em = {r = 200, g = 0, b = 0, a = 128},
lo = {r = 50, g = 50, b = 50, a = 255},
hi = {r = 50, g = 250, b = 50, a = 255},
}
local clr = self.colors
self.signal_pulse_fade = 10
self.int_alpha_loss_max = 0.5
self.pos = pos or {x=491,y=670}
self:SetAutoDelete(true)
self.xml = CScriptXmlInit()
self.xml:ParseFile(xmlfile or "rax_rf_indicator.xml")
self.indicator = self.xml:InitStatic(element or "indicator",self)
if texture then self.indicator:InitTexture(texture) end
self.indicator:SetTextureColor(GetARGB(clr.lo.a, clr.lo.r, clr.lo.g, clr.lo.b))
self.indicator:SetWndPos(vector2():set(self.pos.x, self.pos.y))
self.indicator:EnableHeading(true)
self:ShowIndicator(false)
end
function UIRFWidget:SetSignalColor(sigstr,colors)
if colors and self.colors[sigstr] then
self.colors[sigstr] = colors
end
end
function UIRFWidget:Destroy()
get_hud():RemoveDialogToRender(self)
end
function UIRFWidget:actor_on_net_destroy()
get_hud():RemoveDialogToRender(self)
end
function UIRFWidget:ShowIndicator(onoff)
self.indicator:Show(onoff)
end
function UIRFWidget:SetPos(x,y)
self.pos.x = x or self.pos.x
self.pos.y = y or self.pos.y
self.indicator:SetWndPos(vector2():set(self.pos.x, self.pos.y))
end
function UIRFWidget:SetIndicatorColor(signal, interference,emission, tg)
local tg_emission_noise = math.random(100,400)
local emission_str = 0
local colors = self.colors
local red = colors.lo.r
local green = colors.lo.g
local blue = colors.lo.b
local alpha = colors.lo.a
red = ((colors.lo.r + (colors.hi.r - colors.lo.r) * signal) + red * self.signal_pulse_fade) / (self.signal_pulse_fade + 1)
green = ((colors.lo.g + (colors.hi.g - colors.lo.g) * signal) + green * self.signal_pulse_fade) / (self.signal_pulse_fade + 1)
blue = ((colors.lo.b + (colors.hi.b - colors.lo.b) * signal) + blue * self.signal_pulse_fade) / (self.signal_pulse_fade + 1)
alpha = (((colors.lo.a + (colors.hi.a - colors.lo.a) * signal) - 255 * self.int_alpha_loss_max * interference) + alpha * self.signal_pulse_fade) / (self.signal_pulse_fade +1)
local clr = GetARGB(alpha,red,green,blue)
if emission then
if tg > tg_emission_noise then
emission_str = clamp(emission_str+ math.random(-0.1,0.2),0,1) or 0
tg_emission_noise = math.random(100,400)
end
local r = clamp(red + colors.em.r * emission_str, 0, 255)
local g = clamp(green + colors.em.g * emission_str, 0, 255)
local b = clamp(blue + colors.em.b * emission_str, 0, 255)
local a = clamp(alpha + colors.em.a * emission_str, 0, 255)
clr = GetARGB(a,r,g,b)
else
emission_str = 0
end
self.indicator:SetTextureColor(clr)
end
function UIRFWidget:Update()
if not db.actor then return end
CUIScriptWnd.Update(self)
end
@@ -0,0 +1,198 @@
-- Animation: Append with '_quick' for detectors if:
-- - weapon in main hand is reloading or unjamming
-- - player is climbing
-- - switching to PDA
-- - quick throwing grenades
-- - wiping mask
-- - toggling headlamp
-- - playing an FDDA animation
local common = animation_common
common.add_flag("QUICK_DETECTOR")
-- Flag to force _quick when hiding detectors
force_quick = false
-- Compatibility for FDDA: Use '_quick' if an FDDA animation is about to play
if enhanced_animations then
fdda_anim_prepare = enhanced_animations.anim_prepare
function enhanced_animations.anim_prepare()
force_quick = true
fdda_anim_prepare()
end
fdda_call_my_slot_back = enhanced_animations.call_my_slot_back
function enhanced_animations.call_my_slot_back()
local result = fdda_call_my_slot_back()
if result == true then
force_quick = false
end
return result
end
fdda_bp_call_my_slot_back = zzz_ea_addon_backpack.call_my_slot_back
function zzz_ea_addon_backpack.call_my_slot_back()
local result = fdda_bp_call_my_slot_back()
if result == true then
force_quick = false
end
return result
end
end
-- Switching to PDA (PDA keybind)
-- Beefs nvg switch
function on_key_press(dik)
local bind = dik_to_bind(dik)
-- Quickhide detector when switching on beefs nvgs
if z_beefs_nvgs and bind == key_bindings.kNIGHT_VISION and db.actor:active_detector() then
force_quick = true
return
end
-- PDA keybind
if bind ~= key_bindings.kACTIVE_JOBS then return end
-- Detector drawn
if not db.actor:active_detector() then return end
-- PDA equipped
if not db.actor:item_in_slot(8) then return end
force_quick = true
end
-- Switching to PDA (Map keybind)
function actor_on_first_update()
local activate_slot = db.actor.activate_slot
db.actor.activate_slot = function(self, slot_num)
if slot_num == 8 and db.actor:active_detector() then
force_quick = true
end
activate_slot(self, slot_num)
end
end
-- Toggling headlamp
local Hit_TorchToggle = actor_effects.Hit_TorchToggle
function actor_effects.Hit_TorchToggle()
-- Check if headlamp is equipped. No need for battery check
if (not actor_effects.allow_animation()) or (not item_device.can_toggle_torch()) then
return
end
force_quick = true
Hit_TorchToggle()
end
-- Wiping Mask
local Hit_MaskCleaning = actor_effects.Hit_MaskCleaning
function actor_effects.Hit_MaskCleaning()
-- Check if mask overlay is ON
if (not actor_effects.allow_animation()) or (not actor_effects.is_mask_on()) then
return
end
force_quick = true
Hit_MaskCleaning()
end
-- Quick throw grenade
local Hit_GrenadeQuickthrow = actor_effects.Hit_GrenadeQuickthrow
function actor_effects.Hit_GrenadeQuickthrow()
if (not actor_effects.allow_animation())
or (not db.actor:item_in_slot(4))
or db.actor:get_current_holder() ~= nil
then
return
end
force_quick = true
Hit_GrenadeQuickthrow()
end
---@param item game_object
local function is_item_valid(item)
-- valid if item is equipped detector
local player_detector = db.actor:active_detector()
if player_detector and item:id() == player_detector:id() then
return true
end
return false
end
---@param anm_table any
---@param item game_object
local function anm_quick_detector(anm_table, item)
-- cancel if parent is not player
local parent = item:parent()
if not parent then return end
if parent:id() ~= AC_ID then return end
-- cancel if not valid item
if not is_item_valid(item) then return end
-- Add 'quick' if previous anim was also quick (intended for holster-draw pairs)
if common.get_flag("QUICK_DETECTOR") then
if string.find(anm_table.anm_name, "show") then
common.mutate_anim(anm_table, "_quick", item:section())
end
common.remove_flag("QUICK_DETECTOR")
return
end
local is_state_valid = {
[4] = true, -- inspect
[7] = true, -- reload
[8] = true, -- misfire
}
-- Add 'quick' suffix if above conditions are fulfilled
local player_wpn = db.actor:active_item()
if (
string.find(anm_table.anm_name, "hide")
and (
player_wpn and is_state_valid[player_wpn:get_state()]
or IsMoveState("mcClimb")
or force_quick
)
) then
common.mutate_anim(anm_table, "_quick", item:section())
common.set_flag("QUICK_DETECTOR")
force_quick = false
end
end
common.add_anim_mutator(anm_quick_detector, 5)
-- Use anim mutator to hide detector during inspect animations (added by Utjan)
local inspected_wpn
---@param anm_table any
---@param item game_object
local function inspect_hides_detector(anm_table, item)
-- cancel if parent is not player
local parent = item:parent()
if not parent then return end
if parent:id() ~= AC_ID then return end
if string.find(anm_table.anm_name, "bore") then
local active_det = db.actor:active_detector()
if active_det then
active_det:switch_state(2)
inspected_wpn = item
end
elseif inspected_wpn and inspected_wpn:id() == item:id() then
inspected_wpn = nil
db.actor:show_detector(true)
end
end
common.add_anim_mutator(inspect_hides_detector, 6)
function on_game_start()
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
RegisterScriptCallback("on_key_press", on_key_press)
end
@@ -0,0 +1,110 @@
local common = animation_common
do_ammo_check_anim = nil
wpn_checking, det_active = nil
if ammo_check_mcm then
base_check_Ammo = ammo_check_mcm.check_Ammo
function ammo_check_mcm.check_Ammo()
if ammo_check_mcm.busy_hands_fix then
base_check_Ammo()
return
end
if ammo_check_mcm.actor_on_hud_animation_play then
printf("!Old mag check script (ammo_check_mcm) detected. Remove it to get full features of mag checks")
base_check_Ammo()
return
end
local weapon = db.actor:active_item()
-- ends if no weapon is in hand etc.
if (weapon == nil or (not IsWeapon(weapon)) or IsItem("fake_ammo_wpn", nil, weapon)) then
base_check_Ammo()
return
end
local currentState = weapon:get_state()
if not (currentState == 0 or weapon:weapon_in_grenade_mode()) then
base_check_Ammo()
return
end
-- if magazine weapon
local currentAmmo = weapon:get_ammo_in_magazine()
if (currentAmmo == nil) then
base_check_Ammo()
return
end
local anm_ammo_check = common.has_animation(weapon:section(), "anm_ammo_check")
if not anm_ammo_check then
base_check_Ammo()
return
end
if do_ammo_check_anim then return end -- If an ammo check is already happening, don't do anything
if ammo_check_mcm.busy_hands_fix ~= nil then -- If busy_hands_fix is unlocalized
local prev_hands_fix = ammo_check_mcm.busy_hands_fix
ammo_check_mcm.busy_hands_fix = true
base_check_Ammo()
ammo_check_mcm.busy_hands_fix = prev_hands_fix
else -- Else fall back to workaround
local prev_hands_fix = ui_mcm.get("rax_ammo_check/busy_hands_fix")
ui_mcm.set("rax_ammo_check/busy_hands_fix", true)
ammo_check_mcm.on_option_change()
base_check_Ammo()
ui_mcm.set("rax_ammo_check/busy_hands_fix", prev_hands_fix)
ammo_check_mcm.on_option_change()
end
do_ammo_check_anim = 1
weapon:switch_state(4)
det_active = db.actor:active_detector() or nil
if det_active then
det_active:switch_state(2)
end
--[[ CreateTimeEvent("mag_check", "mag_check_reset", 3, function()
do_ammo_check_anim = nil
return true
end) ]]
end
end
-- Catch the inspect weapon state switch and do the ammo check animation instead
function mag_check_animation(anm_table, obj)
if wpn_checking and obj and wpn_checking:id() == obj:id() and do_ammo_check_anim == 2 then
wpn_checking = nil
do_ammo_check_anim = nil
if det_active then
db.actor:show_detector(true)
end
det_active = nil
end
if do_ammo_check_anim == 1 and obj and obj:get_state() == 4 then
wpn_checking = obj
local is_supported, has_mag_data
if magazine_binder then
is_supported = magazine_binder.is_supported_weapon(obj:section())
has_mag_data = magazine_binder.get_mag_loaded(obj:id())
end
if is_supported and not has_mag_data and common.has_animation(obj:section(), "anm_ammo_check_no_mag") then
anm_table.anm_name = "anm_ammo_check_no_mag"
else
anm_table.anm_name = "anm_ammo_check"
end
do_ammo_check_anim = 2
end
end
if ammo_check_mcm and ammo_check_mcm.actor_on_hud_animation_play then
printf("!Old mag check script (ammo_check_mcm) detected. Remove it to get full features of mag checks")
else
common.add_anim_mutator(mag_check_animation, 0.1)
end
@@ -0,0 +1,7 @@
-- Script to remove the blinking light from the rf-receiver made by utjan
-- This fuction overwrites another one inside the item_radio.script
base_radio_update = item_radio.UI3D_RF.Update
function item_radio.UI3D_RF:Update()
base_radio_update(self)
self.m_led:Show(false)
end