diff --git a/addons/magazinerepack/CfgEventHandlers.hpp b/addons/magazinerepack/CfgEventHandlers.hpp index f0a9f14d91..b928bc2de6 100644 --- a/addons/magazinerepack/CfgEventHandlers.hpp +++ b/addons/magazinerepack/CfgEventHandlers.hpp @@ -1,4 +1,3 @@ - class Extended_PreInit_EventHandlers { class ADDON { init = QUOTE(call COMPILE_FILE(XEH_preInit)); diff --git a/addons/magazinerepack/CfgSounds.hpp b/addons/magazinerepack/CfgSounds.hpp new file mode 100644 index 0000000000..bc1d0fe0ee --- /dev/null +++ b/addons/magazinerepack/CfgSounds.hpp @@ -0,0 +1,15 @@ +class CfgSounds +{ + class GVAR(soundMagazineFinished) + { + name = QGVAR(soundMagazineFinished); + sound[]={QUOTE(PATHTOF(sounds\magrepack_finished.wav)),1,1}; + titles[]={}; + }; + class GVAR(soundRoundFinished) + { + name = QGVAR(soundRoundFinished); + sound[] = {QUOTE(PATHTOF(sounds\magrepack_single.wav)),1,1}; + titles[] = {}; + }; +}; \ No newline at end of file diff --git a/addons/magazinerepack/CfgVehicles.hpp b/addons/magazinerepack/CfgVehicles.hpp index ecb732f8fd..acd1c76c3d 100644 --- a/addons/magazinerepack/CfgVehicles.hpp +++ b/addons/magazinerepack/CfgVehicles.hpp @@ -1,18 +1,17 @@ - class CfgVehicles { - class Man; - class CAManBase: Man { - class ACE_SelfActions { - class ACE_RepackMagazines { - displayName = "$STR_ACE_MagazineRepack_RepackMagazines"; - condition = QUOTE(true); - statement = QUOTE([_player] call FUNC(magazineRepack)); - showDisabled = 0; - priority = -2; - icon = PATHTOF(UI\repack_ca.paa); - hotkey = "R"; - enableInside = 1; - }; + class Man; + class CAManBase: Man { + class ACE_SelfActions { + class ACE_RepackMagazines { + displayName = "$STR_ACE_MagazineRepack_RepackMagazines"; + condition = QUOTE(true); + statement = QUOTE([_player] call FUNC(openSelectMagazineUI)); + showDisabled = 0; + priority = -2; + icon = QUOTE(PATHTOF(UI\repack_ca.paa)); + hotkey = "R"; + enableInside = 1; + }; + }; }; - }; }; diff --git a/addons/magazinerepack/README.md b/addons/magazinerepack/README.md index 49a3c9d531..28b7c3115a 100644 --- a/addons/magazinerepack/README.md +++ b/addons/magazinerepack/README.md @@ -3,10 +3,10 @@ ace_magazinerepack Adds the ability to consolidate multiple half-empty magazines. - ## Maintainers The people responsible for merging changes to this component or answering potential questions. - [commy2](https://github.com/commy2) - [esteldunedain](https://github.com/esteldunedain) +- [PabstMirror](https://github.com/PabstMirror) diff --git a/addons/magazinerepack/XEH_preInit.sqf b/addons/magazinerepack/XEH_preInit.sqf index 5caba1ffac..e2dfd721f3 100644 --- a/addons/magazinerepack/XEH_preInit.sqf +++ b/addons/magazinerepack/XEH_preInit.sqf @@ -2,8 +2,9 @@ ADDON = false; -PREP(magazineRepack); -PREP(magazineRepackCallback); +PREP(magazineRepackProgress); PREP(openSelectMagazineUI); +PREP(simulateRepackEvents); +PREP(startRepackingMagazine); ADDON = true; diff --git a/addons/magazinerepack/config.cpp b/addons/magazinerepack/config.cpp index 5f2c6edc7d..2df0d62bff 100644 --- a/addons/magazinerepack/config.cpp +++ b/addons/magazinerepack/config.cpp @@ -13,6 +13,7 @@ class CfgPatches { }; #include "CfgEventHandlers.hpp" +#include "CfgSounds.hpp" #include "CfgVehicles.hpp" class ACE_Parameters_Numeric { diff --git a/addons/magazinerepack/functions/fnc_magazineRepack.sqf b/addons/magazinerepack/functions/fnc_magazineRepack.sqf deleted file mode 100644 index 472b80e2bd..0000000000 --- a/addons/magazinerepack/functions/fnc_magazineRepack.sqf +++ /dev/null @@ -1,77 +0,0 @@ -// by commy2, esteldunedain -#include "script_component.hpp" - -private ["_unit", "_magazines", "_ammos", "_repackTime", "_magazine", "_ammo", "_count", "_index", "_i", "_j", "_ammoToTransfer", "_ammoAvailable", "_ammoNeeded"]; - -_unit = _this select 0; - -_magazines = []; -_ammos = []; -_repackTime = []; - -// get all mags and ammo count -{ - _magazine = _x select 0; - _ammo = _x select 1; - - _count = getNumber (configfile >> "CfgMagazines" >> _magazine >> "count"); - - if (_ammo != _count && {_count > 1}) then { // additional checks here - if !(_magazine in _magazines) then { - _index = count _magazines; - _magazines set [_index, _magazine]; - _ammos set [_index, [_ammo]]; - } else { - _index = _magazines find _magazine; - _ammos set [_index, (_ammos select _index) + [_ammo]]; - }; - }; -} forEach magazinesAmmoFull _unit; - -// Remove invalid magazines -{ - if (count _x < 2) then { - _magazines set [_forEachIndex, -1]; - _ammos set [_forEachIndex, [-1]]; - }; -} forEach _ammos; -_magazines = _magazines - [-1]; -_ammos = _ammos - [[-1]]; - -{ - // Calculate actual ammo to transfer during repack - _count = getNumber (configfile >> "CfgMagazines" >> (_magazines select _forEachIndex) >> "count"); - - // Sort Ascending - _list = _x call BIS_fnc_sortNum; - - ["MagazineRepack", _list] call EFUNC(common,log); - - _i = 0; - _j = count _x - 1; - _ammoToTransfer = 0; - _ammoAvailable = 0; - while {_i < _j} do { - _ammoNeeded = _count - (_list select _j); - _exit = false; - while {_i < _j && {!_exit}} do { - _ammoAvailable = _list select _i; - if (_ammoAvailable >= _ammoNeeded) then { - _list set [_i, _ammoAvailable - _ammoNeeded]; - _ammoToTransfer = _ammoToTransfer + _ammoNeeded; - _exit = true; - } else { - _ammoNeeded = _ammoNeeded - _ammoAvailable; - _ammoToTransfer = _ammoToTransfer + _ammoAvailable; - _i = _i + 1; - }; - }; - _j = _j - 1; - }; - - _repackTime set [_forEachIndex, _ammoToTransfer * GVAR(TimePerAmmo) + (count _x) * GVAR(TimePerMagazine)]; -} forEach _ammos; - -["MagazineRepack", [_magazines, _repackTime]] call EFUNC(common,log); - -[_unit, _magazines, _repackTime] call FUNC(openSelectMagazineUI); diff --git a/addons/magazinerepack/functions/fnc_magazineRepackCallback.sqf b/addons/magazinerepack/functions/fnc_magazineRepackCallback.sqf deleted file mode 100644 index f209806f9c..0000000000 --- a/addons/magazinerepack/functions/fnc_magazineRepackCallback.sqf +++ /dev/null @@ -1,106 +0,0 @@ -// by commy2 -#include "script_component.hpp" - -private ["_unit", "_magazine", "_ammo", "_ammoCount", "_fullMagazinesCount", "_restAmmo", "_isLoaded", "_weapon", "_reloadAction", "_text", "_picture"]; - -_unit = ACE_player; //_this select 0; -_magazine = _this select 1; - -// exit if the last magazine of this type was taken out of the backpack -if !(_magazine in magazines _unit) exitWith {}; - -// get current ammo count -_ammo = 0; -{ - if (_x select 0 == _magazine) then { - _ammo = _ammo + (_x select 1); - }; -} forEach magazinesAmmoFull _unit; - -// how many rounds fit in one mag -_ammoCount = getNumber (configFile >> "CfgMagazines" >> _magazine >> "count"); - -// calculate new vaules -_fullMagazinesCount = floor (_ammo / _ammoCount); -_restAmmo = _ammo - _fullMagazinesCount * _ammoCount; - -// remove old magazines -_unit removeMagazines _magazine; - -_isLoaded = false; -// reload rifle -if (_magazine in primaryWeaponMagazine _unit) then { - _weapon = primaryWeapon _unit; - - if (_fullMagazinesCount > 0) then { - _unit setAmmo [_weapon, _ammoCount]; - _fullMagazinesCount = _fullMagazinesCount - 1; - } else { - _unit setAmmo [_weapon, _restAmmo]; - _restAmmo = 0; - }; - - if (_weapon == currentWeapon _unit) then { - _reloadAction = getText (configFile >> "CfgWeapons" >> _weapon >> "reloadAction"); - _unit playActionNow _reloadAction; - }; - - _isLoaded = true; -}; - -// reload pistol -if (_magazine in handgunMagazine _unit) then { - _weapon = handgunWeapon _unit; - - if (_fullMagazinesCount > 0) then { - _unit setAmmo [_weapon, _ammoCount]; - _fullMagazinesCount = _fullMagazinesCount - 1; - } else { - _unit setAmmo [_weapon, _restAmmo]; - _restAmmo = 0; - }; - - if (_weapon == currentWeapon _unit) then { - _reloadAction = getText (configFile >> "CfgWeapons" >> _weapon >> "reloadAction"); - _unit playActionNow _reloadAction; - }; - - _isLoaded = true; -}; - -// reload rocket launcher (just in case ...) -if (_magazine in secondaryWeaponMagazine _unit) then { - _weapon = secondaryWeapon _unit; - - if (_fullMagazinesCount > 0) then { - _unit setAmmo [_weapon, _ammoCount]; - _fullMagazinesCount = _fullMagazinesCount - 1; - } else { - _unit setAmmo [_weapon, _restAmmo]; - _restAmmo = 0; - }; - - if (_weapon == currentWeapon _unit) then { - _reloadAction = getText (configFile >> "CfgWeapons" >> _weapon >> "reloadAction"); - _unit playActionNow _reloadAction; - }; - - _isLoaded = true; -}; - -// add new magazines -for "_a" from 1 to _fullMagazinesCount do { - _unit addMagazine _magazine; -}; - -if (_restAmmo > 0) then { - _unit addMagazine [_magazine, _restAmmo]; -}; - -// display text if successful -_text = format [localize "STR_ACE_MagazineRepack_RepackedMagazinesDetail", [_fullMagazinesCount, _fullMagazinesCount + 1] select _isLoaded, _restAmmo]; -_picture = getText (configFile >> "CfgMagazines" >> _magazine >> "picture"); - -_text = parseText format ["
%2
%3", _picture, localize "STR_ACE_MagazineRepack_RepackedMagazines", _text]; - -[_text] call EFUNC(common,displayTextStructured); diff --git a/addons/magazinerepack/functions/fnc_magazineRepackProgress.sqf b/addons/magazinerepack/functions/fnc_magazineRepackProgress.sqf new file mode 100644 index 0000000000..f965305eda --- /dev/null +++ b/addons/magazinerepack/functions/fnc_magazineRepackProgress.sqf @@ -0,0 +1,70 @@ +// by commy2, esteldunedain +#include "script_component.hpp" + +PARAMS_3(_args,_elapsedTime,_totalTime); +EXPLODE_3_PVT(_args,_magazineClassname,_lastAmmoCount,_simEvents); + +if ((count _simEvents) == 0) exitWith {ERROR("No Event"); false}; +EXPLODE_3_PVT((_simEvents select 0),_nextEventTime,_nextEventType,_nextEventMags); + + + +if (_nextEventTime > _elapsedTime) exitWith {true};//waiting on next event +systemChat format ["Event %1-%2-%3", _nextEventTime,_nextEventType,_nextEventMags]; + + +//Verify we aren't missing any ammo +_currentAmmoCount = []; +{ + EXPLODE_2_PVT(_x,_xClassname,_xCount); + if (_xClassname == _magazineClassname) then { + _currentAmmoCount pushBack _xCount; + }; +} forEach (magazinesAmmo ACE_player); //only inventory mags + +_addedMagazines = +_currentAmmoCount; +_missingAmmo = false; +{ + if (_x > 0) then { + _index = _addedMagazines find _x; + if (_index != -1) then { + _addedMagazines deleteAt _index; + } else { + _missingAmmo = true; + }; + }; +} forEach _lastAmmoCount; + +if (_missingAmmo) exitWith {false}; //something removed ammo that was being repacked +if ((count _addedMagazines) > 0) then { + TRACE_1("Added Magazine While Repacking",_addedMagazines); +}; + +_updateMagazinesOnPlayer = { + systemChat format ["Updating mags"]; + _newMagazineList = _addedMagazines + _nextEventMags; + ACE_player removeMagazines _magazineClassname; + { + if (_x > 0) then { + ACE_player addMagazine [_magazineClassname, _x]; + }; + } forEach _newMagazineList; + _args set [1, _nextEventMags]; +}; + + +if (_nextEventType == 0) then { + systemChat "reloading bullet"; + playSound QGVAR(soundMagazineFinished); + if (((count _simEvents) % 3) == 0) then { + call _updateMagazinesOnPlayer; + }; +} else { + systemChat "Moving to next mag"; + playSound QGVAR(soundRoundFinished); + call _updateMagazinesOnPlayer; +}; + +_simEvents deleteAt 0; //pop off the event + +true; diff --git a/addons/magazinerepack/functions/fnc_openSelectMagazineUI.sqf b/addons/magazinerepack/functions/fnc_openSelectMagazineUI.sqf index b1a31c266c..931a0149cf 100644 --- a/addons/magazinerepack/functions/fnc_openSelectMagazineUI.sqf +++ b/addons/magazinerepack/functions/fnc_openSelectMagazineUI.sqf @@ -1,40 +1,47 @@ -// by commy2 +// by commy2, esteldunedain #include "script_component.hpp" -private ["_unit", "_magazines", "_repackTime", "_listIDC", "_count", "_index", "_magazine", "_time", "_displayName", "_picture"]; +private ["_unit", "_magazines", "_ammos", "_repackTime", "_magazine", "_ammo", "_count", "_index", "_i", "_j", "_ammoToTransfer", "_ammoAvailable", "_ammoNeeded"]; -_unit = _this select 0; -_magazines = _this select 1; -_repackTime = _this select 2; +PARAMS_1(_unit); -_count = count _magazines; +_unitMagazines = []; +_unitMagCounts = []; + +// get all mags and ammo count +{ + _xClassname = _x select 0; + _xCount = _x select 1; + _fullMagazineCount = getNumber (configfile >> "CfgMagazines" >> _xClassname >> "count"); + + if ((_xCount != _fullMagazineCount) && {_xCount > 1}) then {//for every partial magazine + _index = _unitMagazines find _xClassname; + if (_index == -1) then { + _unitMagazines pushBack _xClassname; + _unitMagCounts pushBack [_xCount]; + } else { + (_unitMagCounts select _index) pushBack _xCount; + }; + }; +} forEach magazinesAmmoFull _unit; _actions = [localize "STR_ACE_MagazineRepack_SelectMagazineMenu", localize "STR_ACE_MagazineRepack_SelectMagazine"] call EFUNC(interaction,prepareSelectMenu); -for "_index" from 0 to (_count - 1) do { - _magazine = _magazines select _index; - _time = _repackTime select _index; - _displayName = getText (configFile >> "CfgMagazines" >> _magazine >> "displayName"); - _picture = getText (configFile >> "CfgMagazines" >> _magazine >> "picture"); - _actions = [ - _actions, - _displayName, - _picture, - [str _unit, _magazine, _time] - ] call EFUNC(interaction,addSelectableItem); -}; + +systemChat format ["%1 - %2", _unitMagazines, _unitMagCounts]; + +{ + if ((count (_unitMagCounts select _forEachIndex)) >= 2) then {// Ignore invalid magazines types (need 2+ partial mags to do anything) + _displayName = getText (configFile >> "CfgMagazines" >> _x >> "displayName"); + _picture = getText (configFile >> "CfgMagazines" >> _x >> "picture"); + _actions = [_actions, _displayName, _picture, _x] call EFUNC(interaction,addSelectableItem); + }; +} forEach _unitMagazines; [ - _actions, - { - _data = _this; - call EFUNC(interaction,hideMenu); - if (isNil "_data") exitWith {}; - _data set [2, [_data select 2] call EFUNC(common,toNumber)]; - [(_data select 2), _data, {(_this select 0) call FUNC(magazineRepackCallback)}, {}, (localize "STR_ACE_MagazineRepack_RepackingMagazine")] call EFUNC(common,progressBar); - [ACE_player] call EFUNC(common,goKneeling); - }, - { - call EFUNC(interaction,hideMenu); - if !(profileNamespace getVariable [QGVAR(AutoCloseMenu), false]) then {"Default" call EFUNC(interaction,openMenuSelf)}; - } +_actions, +{ [ACE_player, _this] call FUNC(startRepackingMagazine); }, +{ + call EFUNC(interaction,hideMenu); + if !(profileNamespace getVariable [QGVAR(AutoCloseMenu), false]) then {"Default" call EFUNC(interaction,openMenuSelf)}; +} ] call EFUNC(interaction,openSelectMenu); diff --git a/addons/magazinerepack/functions/fnc_simulateRepackEvents.sqf b/addons/magazinerepack/functions/fnc_simulateRepackEvents.sqf new file mode 100644 index 0000000000..9df248bd6c --- /dev/null +++ b/addons/magazinerepack/functions/fnc_simulateRepackEvents.sqf @@ -0,0 +1,52 @@ +#include "script_component.hpp" + +private ["_fullMagazineCount", "_magazines", "_newMag", "_time", "_events", "_swapAmmo", "_ammoSwaped", "_lowIndex", "_highIndex", "_ammoToTransfer", "_ammoAvailable", "_ammoNeeded"]; + +PARAMS_2(_magazineClassname,_arrayOfAmmoCounts); + +// Calculate actual ammo to transfer during repack +_fullMagazineCount = getNumber (configfile >> "CfgMagazines" >> _magazineClassname >> "count"); + +// Sort Ascending - Don't modify orginal +_arrayOfAmmoCounts = (+_arrayOfAmmoCounts) call BIS_fnc_sortNum; + +_newMag = { + _time = _time + GVAR(TimePerMagazine); + _events pushBack [_time, 1, +_arrayOfAmmoCounts]; +}; +_swapAmmo = { + for "_swapProgress" from 1 to _ammoSwaped do { + _time = _time + GVAR(TimePerAmmo); + _arrayOfAmmoCounts set [_lowIndex, ((_arrayOfAmmoCounts select _lowIndex) - 1)]; + _arrayOfAmmoCounts set [_highIndex, ((_arrayOfAmmoCounts select _highIndex) + 1)]; + _events pushBack [_time, 0, +_arrayOfAmmoCounts]; + }; +}; + +_lowIndex = 0; +_highIndex = (count _arrayOfAmmoCounts) - 1; +_ammoToTransfer = 0; +_ammoAvailable = 0; + +_time = 0; +_events = []; + +while {_lowIndex < _highIndex} do { + _ammoNeeded = _fullMagazineCount - (_arrayOfAmmoCounts select _highIndex); + _ammoAvailable = _arrayOfAmmoCounts select _lowIndex; + + if (_ammoAvailable == 0) then { + _lowIndex = _lowIndex + 1; + call _newMag; + } else { + if (_ammoNeeded == 0) then { + _highIndex = _highIndex - 1; + call _newMag; + } else { + _ammoSwaped = _ammoAvailable min _ammoNeeded; + call _swapAmmo; + }; + }; +}; + +_events diff --git a/addons/magazinerepack/functions/fnc_startRepackingMagazine.sqf b/addons/magazinerepack/functions/fnc_startRepackingMagazine.sqf new file mode 100644 index 0000000000..8e5075e17e --- /dev/null +++ b/addons/magazinerepack/functions/fnc_startRepackingMagazine.sqf @@ -0,0 +1,39 @@ +// by commy2, esteldunedain +#include "script_component.hpp" + +private ["_unit", "_magazines", "_ammos", "_repackTime", "_magazine", "_ammo", "_count", "_index", "_i", "_j", "_ammoToTransfer", "_ammoAvailable", "_ammoNeeded"]; + +PARAMS_2(_unit,_magazineClassname); +if (isNil "_magazineClassname" || {_magazineClassname == ""}) exitWith {ERROR("Bad Mag Classname");}; + +[_unit] call EFUNC(common,goKneeling); +call EFUNC(interaction,hideMenu); + +_startingAmmoCounts = []; +{ + EXPLODE_4_PVT(_x,_xClassname,_xCount,_xLoaded,_xType); + if (_xClassname == _magazineClassname) then { + if (_xLoaded) then { + //Try to Remove from weapon and add to inventory, otherwise ignore + if (_unit canAdd _magazineClassname) then { + switch (_xType) do { + case (1): {_unit removePrimaryWeaponItem _magazineClassname;}; + case (2): {_unit removeHandgunItem _magazineClassname;}; + case (4): {_unit removeSecondaryWeaponItem _magazineClassname;}; + default {ERROR("Loaded Location Invalid");}; + }; + _unit addMagazine [_magazineClassname, _xCount]; + _startingAmmoCounts pushBack _xCount; + }; + } else { + _startingAmmoCounts pushBack _xCount; + }; + }; +} forEach (magazinesAmmoFull _unit); + +if ((count _startingAmmoCounts) == 0) exitwith {ERROR("No Mags");}; + +_simEvents = [_magazineClassname, _startingAmmoCounts] call FUNC(simulateRepackEvents); +_totalTime = (_simEvents select ((count _simEvents) - 1) select 0); + +[_totalTime, [_magazineClassname, _startingAmmoCounts, _simEvents], {hint "done"}, {hint "fail"}, (localize "STR_ACE_MagazineRepack_RepackingMagazine"), {_this call FUNC(magazineRepackProgress)}] call EFUNC(common,progressBar); diff --git a/addons/magazinerepack/script_component.hpp b/addons/magazinerepack/script_component.hpp index 7b390f7126..15563f0fe8 100644 --- a/addons/magazinerepack/script_component.hpp +++ b/addons/magazinerepack/script_component.hpp @@ -1,3 +1,5 @@ +#define DEBUG_MODE_FULL + #define COMPONENT magazinerepack #include "\z\ace\addons\main\script_mod.hpp" diff --git a/addons/magazinerepack/sounds/magrepack_finished.wav b/addons/magazinerepack/sounds/magrepack_finished.wav new file mode 100644 index 0000000000..ab73615a55 Binary files /dev/null and b/addons/magazinerepack/sounds/magrepack_finished.wav differ diff --git a/addons/magazinerepack/sounds/magrepack_single.wav b/addons/magazinerepack/sounds/magrepack_single.wav new file mode 100644 index 0000000000..5d94e215fd Binary files /dev/null and b/addons/magazinerepack/sounds/magrepack_single.wav differ