local repo = 'https://raw.githubusercontent.com/violin-suzutsuki/LinoriaLib/main/' local Library = loadstring(game:HttpGet(repo .. 'Library.lua'))() local ThemeManager = loadstring(game:HttpGet(repo .. 'addons/ThemeManager.lua'))() local SaveManager = loadstring(game:HttpGet(repo .. 'addons/SaveManager.lua'))() local Window = Library:CreateWindow({ Title = 'Weapon Tweaks', Center = true, AutoShow = true, TabPadding = 8, MenuFadeTime = 0.2, }) local Tabs = { Main = Window:AddTab('Main'), ['UI Settings'] = Window:AddTab('UI Settings'), } local Group = Tabs.Main:AddLeftGroupbox('Weapon Tweaks') Group:AddToggle('RapidFire', { Text = 'Rapid Fire', Default = false, Tooltip = 'removes delay from any gun', }) Group:AddSlider('RapidFireRate', { Text = 'Fire Rate Delay', Default = 0, Min = 0, Max = 1, Rounding = 3, Suffix = 's', Tooltip = 'shots delay (0 = max)', }) Group:AddToggle('NoEquipDelay', { Text = 'No Equip Delay (fix it by urself)', Default = false, Tooltip = 'shoot after equip', }) Group:AddDivider() Group:AddToggle('FullAuto', { Text = 'Full Auto', Default = false, Tooltip = 'hold lmb — gun will be shoot automaticaly Semi Pump Burst', }) Group:AddSlider('FullAutoRate', { Text = 'Full Auto Interval', Default = 0, Min = 0, Max = 0.5, Rounding = 3, Suffix = 's', Tooltip = 'Minimal interval of rapidfire in full auto (0 = every frame)', }) Group:AddDivider() local StatusLabel = Group:AddLabel('Status: finding hooks...', true) local function findWeaponMetatable() for _, obj in pairs(getgc(true)) do if type(obj) == 'table' then local lookup = rawget(obj, 'WeaponLookup') if type(lookup) == 'table' and rawget(obj, 'LastFireTime') ~= nil and rawget(obj, 'LastEquipTime') ~= nil and rawget(obj, 'IsEquipped') ~= nil then return getmetatable(obj) end end end end local function findFireModes() for _, obj in pairs(getgc(true)) do if type(obj) == 'table' and type(rawget(obj, 'Auto')) == 'function' and type(rawget(obj, 'Semi')) == 'function' and type(rawget(obj, 'Pump')) == 'function' and type(rawget(obj, 'Burst')) == 'function' then return obj end end end local fireModesHooked = false local weaponHooked = false local function refreshStatus() if fireModesHooked and weaponHooked then StatusLabel:SetText('Status: hooks are active') elseif fireModesHooked then StatusLabel:SetText('Status: FireModes, waiting for a gun...') elseif weaponHooked then StatusLabel:SetText('Status: Weapon, waiting for FireModes...') else StatusLabel:SetText('Status: finding hooks...') end end local function effectiveRate(defaultRate) if Toggles.RapidFire and Toggles.RapidFire.Value then return (Options.RapidFireRate and Options.RapidFireRate.Value) or 0 end return defaultRate end local function makeFireModeHook(modeName, original) return function(self, rate) local r = effectiveRate(rate) if modeName ~= 'Auto' and Toggles.FullAuto and Toggles.FullAuto.Value then if self.IsFiring then return end self.IsFiring = true local interval = (Options.FullAutoRate and Options.FullAutoRate.Value) or 0 task.spawn(function() while self.IsFiring and self.IsEquipped and not self.Destroyed do local rr = effectiveRate(rate) original(self, rr) if interval > 0 then task.wait(interval) else task.wait() end end end) return end return original(self, r) end end task.spawn(function() local attempts = 0 while not fireModesHooked do attempts += 1 local ok, modes = pcall(findFireModes) modes = ok and modes or nil if modes then for _, name in ipairs({'Auto', 'Semi', 'Pump', 'Burst'}) do local original = modes[name] if type(original) == 'function' then modes[name] = makeFireModeHook(name, original) end end fireModesHooked = true refreshStatus() else if attempts >= 15 then StatusLabel:SetText('Status: FireModes not found') return end task.wait(1) end end end) task.spawn(function() local attempts = 0 while not weaponHooked do attempts += 1 local ok, mt = pcall(findWeaponMetatable) mt = ok and mt or nil if mt then local original = mt.Fire if type(original) == 'function' then mt.Fire = function(self, ...) if Toggles.NoEquipDelay and Toggles.NoEquipDelay.Value then self.LastEquipTime = -1e15 end return original(self, ...) end weaponHooked = true refreshStatus() end else if attempts >= 15 then StatusLabel:SetText('Status: No gun found (enter the match)') return end task.wait(1) end end end) local MenuGroup = Tabs['UI Settings']:AddLeftGroupbox('Menu') MenuGroup:AddButton('Unload', function() Library:Unload() end) MenuGroup:AddLabel('Menu bind'):AddKeyPicker('MenuKeybind', { Default = 'End', NoUI = true, Text = 'Menu keybind', }) Library.ToggleKeybind = Options.MenuKeybind ThemeManager:SetLibrary(Library) SaveManager:SetLibrary(Library) SaveManager:IgnoreThemeSettings() SaveManager:SetIgnoreIndexes({ 'MenuKeybind' }) ThemeManager:SetFolder('WeaponTweaks') SaveManager:SetFolder('WeaponTweaks') SaveManager:BuildConfigSection(Tabs['UI Settings']) ThemeManager:ApplyToTab(Tabs['UI Settings'])