Merge pull request #136 from acemod/disarmingTest

Unit Disarming/DropGear Merge
This commit is contained in:
PabstMirror 2015-04-11 14:14:22 -05:00
commit f5cce94b91
24 changed files with 968 additions and 0 deletions

View File

@ -0,0 +1 @@
z\ace\addons\disarming

View File

@ -0,0 +1,11 @@
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preInit));
};
};
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_postInit));
};
};

View File

@ -0,0 +1,17 @@
class CfgVehicles {
class Man;
class CAManBase: Man {
class ACE_Actions {
class ACE_MainActions {
class ACE_DisarmInventory {
displayName = "$STR_ACE_Disarming_OpenInventory";
distance = 3.5;
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canPlayerDisarmUnit));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(openDisarmDialog));
icon = "\a3\Modules_F_Curator\Data\portraitRespawnInventory_ca.paa";
exceptions[] = {};
};
};
};
};
};

View File

@ -0,0 +1,14 @@
class CfgWeapons {
class ACE_ItemCore;
class InventoryItem_Base_F;
class ACE_DebugPotato: ACE_ItemCore {
displayName = "ACE Potato (debug)";
descriptionShort = "Glorious Potato<br/>If you see this in game it means someone fucked up";
picture = QUOTE(PATHTOF(UI\potato_ca.paa));
scope = 1;
class ItemInfo: InventoryItem_Base_F {
mass = 1;
};
};
};

View File

@ -0,0 +1,11 @@
ace_disarming
============
Adds ability to make units drop items/weapons/magazines.
## Maintainers
The people responsible for merging changes to this component or answering potential questions.
- [PabstMirror](https://github.com/PabstMirror)

Binary file not shown.

View File

@ -0,0 +1,4 @@
#include "script_component.hpp"
["DisarmDropItems", {_this call FUNC(eventTargetStart)}] call EFUNC(common,addEventHandler);
["DisarmDebugCallback", {_this call FUNC(eventCallerFinish)}] call EFUNC(common,addEventHandler);

View File

@ -0,0 +1,17 @@
#include "script_component.hpp"
ADDON = false;
PREP(canBeDisarmed);
PREP(canPlayerDisarmUnit);
PREP(disarmDropItems);
PREP(eventCallerFinish);
PREP(eventTargetFinish);
PREP(eventTargetStart);
PREP(getAllGearContainer);
PREP(getAllGearUnit);
PREP(openDisarmDialog);
PREP(showItemsInListbox);
PREP(verifyMagazinesMoved);
ADDON = true;

View File

@ -0,0 +1,19 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
units[] = {};
weapons[] = {"ACE_DebugPotato"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ACE_Interaction"};
author[] = {"PabstMirror"};
authorUrl = "https://github.com/PabstMirror/";
VERSION_CONFIG;
};
};
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"
#include "CfgWeapons.hpp"
#include "gui_disarm.hpp"

View File

@ -0,0 +1,34 @@
/*
* Author: PabstMirror
* Checks the conditions for being able to disarm a unit
*
* Arguments:
* 0: Target <OBJECT>
*
* Return Value:
* Can Be Disarmed <BOOL>
*
* Example:
* [cursorTarget] call ace_disarming_fnc_canBeDisarmed
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_1(_target);
//Check animationState for putDown anim
//This ensures the unit doesn't have to actualy do any animation to drop something
//This should always be true for the 3 possible status effects that allow disarming
_animationStateCfgMoves = getText (configFile >> "CfgMovesMaleSdr" >> "States" >> (animationState _target) >> "actions");
if (_animationStateCfgMoves == "") exitWith {false};
_putDownAnim = getText (configFile >> "CfgMovesBasic" >> "Actions" >> _animationStateCfgMoves >> "PutDown");
if (_putDownAnim != "") exitWith {false};
(alive _target) &&
{(abs (speed _target)) < 1} &&
{(vehicle _target) == _target} &&
{(_target getVariable ["ACE_isUnconscious", false]) ||
{_target getVariable [QEGVAR(captives,isHandcuffed), false]} ||
{_target getVariable [QEGVAR(captives,isSurrendering), false]}}

View File

@ -0,0 +1,22 @@
/*
* Author: PabstMirror
* Checks the conditions for being able to disarm a unit
*
* Arguments:
* 0: Player <OBJECT>
* 1: Target <OBJECT>
*
* Return Value:
* Can Be Disarm Target <BOOL>
*
* Example:
* [player, cursorTarget] call ace_disarming_fnc_canPlayerDisarmUnit
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_2(_player,_target);
([_target] call FUNC(canBeDisarmed)) &&
{([_player, _target, []] call EFUNC(common,canInteractWith))}

View File

@ -0,0 +1,252 @@
/*
* Author: PabstMirror
* Makes a unit drop items
*
* Arguments:
* 0: caller (player) <OBJECT>
* 1: target <OBJECT>
* 2: classnamess <ARRAY>
* 3: Do Not Drop Ammo <BOOL><OPTIONAL>
*
* Return Value:
* Nothing
*
* Example:
* [player, cursorTarget, ["ace_bandage"]] call ace_disarming_fnc_disarmDropItems
*
* Public: No
*/
#include "script_component.hpp"
#define TIME_MAX_WAIT 5
PARAMS_3(_caller,_target,_listOfItemsToRemove);
DEFAULT_PARAM(3,_doNotDropAmmo,false); //By default units drop all weapon mags when dropping a weapon
_fncSumArray = {
_return = 0;
{_return = _return + _x;} forEach (_this select 0);
_return
};
//Sanity Checks
if (!([_target] call FUNC(canBeDisarmed))) exitWith {
[_caller, _target, "Debug: Cannot disarm target"] call FUNC(eventTargetFinish);
};
if (_doNotDropAmmo && {({_x in _listOfItemsToRemove} count (magazines _target)) > 0}) exitWith {
[_caller, _target, "Debug: Trying to drop magazine with _doNotDropAmmo flag"] call FUNC(eventTargetFinish);
};
_holder = objNull;
//If not dropping ammo, don't use an existing container
if (!_doNotDropAmmo) then {
{
if ((_x getVariable [QGVAR(disarmUnit), objNull]) == _target) exitWith {
_holder = _x;
};
} forEach ((getpos _target) nearObjects [DISARM_CONTAINER, 3]);
};
//Create a new weapon holder
if (isNull _holder) then {
_dropPos = _target modelToWorld [0.4, 0.75, 0]; //offset someone unconscious isn't lying over it
_dropPos set [2, ((getPosASL _target) select 2)];
_holder = createVehicle [DISARM_CONTAINER, _dropPos, [], 0, "CAN_COLLIDE"];
_holder setPosASL _dropPos;
_holder setVariable [QGVAR(disarmUnit), _target, true];
};
//Verify holder created
if (isNull _holder) exitWith {
[_caller, _target, "Debug: Null Holder"] call FUNC(eventTargetFinish);
};
//Make sure only one drop operation at a time (using PFEH system as a queue)
if (_holder getVariable [QGVAR(holderInUse), false]) exitWith {
[{
_this call FUNC(disarmDropItems);
}, _this, 0, 0] call EFUNC(common,waitAndExecute);
};
_holder setVariable [QGVAR(holderInUse), true];
//Remove Magazines
_targetMagazinesStart = magazinesAmmo _target;
_holderMagazinesStart = magazinesAmmoCargo _holder;
{
EXPLODE_2_PVT(_x,_xClassname,_xAmmo);
if ((_xClassname in _listOfItemsToRemove) && {!(_xClassname in UNIQUE_MAGAZINES)}) then {
_holder addMagazineAmmoCargo [_xClassname, 1, _xAmmo];
_target removeMagazine _xClassname;
};
} forEach _targetMagazinesStart;
_targetMagazinesEnd = magazinesAmmo _target;
_holderMagazinesEnd = magazinesAmmoCargo _holder;
//Verify Mags dropped from unit:
if ( ({((_x select 0) in _listOfItemsToRemove) && {!((_x select 0) in UNIQUE_MAGAZINES)}} count _targetMagazinesEnd) != 0) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Didn't Remove Magazines"] call FUNC(eventTargetFinish);
};
//Verify holder has mags unit had
if (!([_targetMagazinesStart, _targetMagazinesEnd, _holderMagazinesStart, _holderMagazinesEnd] call FUNC(verifyMagazinesMoved))) then {
ERR = [_targetMagazinesStart, _targetMagazinesEnd, _holderMagazinesStart, _holderMagazinesEnd];
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Crate Magazines not in holder"] call FUNC(eventTargetFinish);
};
//Remove Items, Assigned Items and NVG
_holderItemsStart = getitemCargo _holder;
_targetItemsStart = (assignedItems _target) + (items _target);
if ((headgear _target) != "") then {_targetItemsStart pushBack (headgear _target);};
if ((goggles _target) != "") then {_targetItemsStart pushBack (goggles _target);};
_addToCrateClassnames = [];
_addToCrateCount = [];
{
if (_x in _listOfItemsToRemove) then {
if (_x in (items _target)) then {
_target removeItem _x;
} else {
_target unlinkItem _x;
};
_index = _addToCrateClassnames find _x;
if (_index != -1) then {
_addToCrateCount set [_index, ((_addToCrateCount select _index) + 1)];
} else {
_addToCrateClassnames pushBack _x;
_addToCrateCount pushBack 1;
};
};
} forEach _targetItemsStart;
//Add the items to the holder (combined to reduce addItemCargoGlobal calls)
{
_holder addItemCargoGlobal [(_addToCrateClassnames select _forEachIndex), (_addToCrateCount select _forEachIndex)];
} forEach _addToCrateClassnames;
_holderItemsEnd = getitemCargo _holder;
_targetItemsEnd = (assignedItems _target) + (items _target);
if ((headgear _target) != "") then {_targetItemsEnd pushBack (headgear _target);};
if ((goggles _target) != "") then {_targetItemsEnd pushBack (goggles _target);};
//Verify Items Added
if (((count _targetItemsStart) - (count _targetItemsEnd)) != ([_addToCrateCount] call _fncSumArray)) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Items Not Removed From Player"] call FUNC(eventTargetFinish);
};
if ((([_holderItemsEnd select 1] call _fncSumArray) - ([_holderItemsStart select 1] call _fncSumArray)) != ([_addToCrateCount] call _fncSumArray)) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Items Not Added to Holder"] call FUNC(eventTargetFinish);
};
//If holder is still empty, it will be 'garbage collected' while we wait for the drop 'action' to take place
//So add a dummy item and just remove at the end
_holderIsEmpty = ([_holder] call FUNC(getAllGearContainer)) isEqualTo [[],[]];
if (_holderIsEmpty) then {
TRACE_1("Debug: adding dummy item to holder",_holder);
_holder addItemCargoGlobal [DUMMY_ITEM, 1];
};
//Start the PFEH to do the actions (which could take >1 frame)
[{
PARAMS_2(_args,_pfID);
EXPLODE_8_PVT(_args,_caller,_target,_listOfItemsToRemove,_holder,_holderIsEmpty,_maxWaitTime,_doNotDropAmmo,_startingMagazines);
_needToRemoveWeapon = ({_x in _listOfItemsToRemove} count (weapons _target)) > 0;
_needToRemoveMagazines = ({_x in _listOfItemsToRemove} count (magazines _target)) > 0;
_needToRemoveBackpack = ((backPack _target) != "") && {(backPack _target) in _listOfItemsToRemove};
_needToRemoveVest = ((vest _target) != "") && {(vest _target) in _listOfItemsToRemove};
_needToRemoveUniform = ((uniform _target) != "") && {(uniform _target) in _listOfItemsToRemove};
if ((time < _maxWaitTime) && {[_target] call FUNC(canBeDisarmed)} && {_needToRemoveWeapon || _needToRemoveMagazines || _needToRemoveBackpack}) then {
//action drop weapons (keeps loaded magazine and attachements)
{
if (_x in _listOfItemsToRemove) then {
_target action ["DropWeapon", _holder, _x];
};
} forEach (weapons _target);
//Drop magazine (keeps unique ID)
{
if (_x in _listOfItemsToRemove) then {
_target action ["DropMagazine", _holder, _x];
};
} forEach (magazines _target);
//Drop backpack (Keeps variables for ACRE/TFR)
if (_needToRemoveBackpack) then {_target action ["DropBag", _holder, (backPack _target)];};
} else {
[_pfID] call CBA_fnc_removePerFrameHandler;
if (_doNotDropAmmo) then {
_error = false;
_magsToPickup = +_startingMagazines;
{
_index = _magsToPickup find _x;
if (_index == -1) exitWith {_error = true; ERROR("More mags than when we started?")};
_magsToPickup deleteAt _index;
} forEach (magazinesAmmo _target);
_magazinesInHolder = magazinesAmmoCargo _holder;
{
_index = _magazinesInHolder find _x;
if (_index == -1) exitWith {_error = true; ERROR("Missing mag not in holder")};
_magazinesInHolder deleteAt _index;
} forEach _magsToPickup;
//No Error (all the ammo in the container is ammo we should have);
if ((!_error) && {_magazinesInHolder isEqualTo []}) then {
{
_target addMagazine _x;
} forEach (magazinesAmmoCargo _holder);
clearMagazineCargoGlobal _holder;
};
};
//If we added a dummy item, remove it now
if (_holderIsEmpty && {!((getItemCargo _holder) isEqualTo [[DUMMY_ITEM],[1]])}) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Holder should only have dummy item"] call FUNC(eventTargetFinish);
};
if (_holderIsEmpty) then {
TRACE_1("Debug: removing dummy item from holder",_holder);
clearItemCargoGlobal _holder;
};
//Verify we didn't timeout waiting on drop action
if (time >= _maxWaitTime) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Drop Actions Timeout"] call FUNC(eventTargetFinish);
};
//If target lost disarm status:
if (!([_target] call FUNC(canBeDisarmed))) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Target cannot be disarmed"] call FUNC(eventTargetFinish);
};
if (_needToRemoveVest && {!((vestItems _target) isEqualTo [])}) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Vest Not Empty"] call FUNC(eventTargetFinish);
};
if (_needToRemoveVest) then {
_holder addItemCargoGlobal [(vest _target), 1];
removeVest _target;
};
if (_needToRemoveUniform && {!((uniformItems _target) isEqualTo [])}) exitWith {
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, "Debug: Uniform Not Empty"] call FUNC(eventTargetFinish);
};
if (_needToRemoveUniform) then {
_holder addItemCargoGlobal [(uniform _target), 1];
removeUniform _target;
};
_holder setVariable [QGVAR(holderInUse), false];
[_caller, _target, ""] call FUNC(eventTargetFinish);
};
}, 0.0, [_caller,_target, _listOfItemsToRemove, _holder, _holderIsEmpty, (time + TIME_MAX_WAIT), _doNotDropAmmo, _targetMagazinesEnd]] call CBA_fnc_addPerFrameHandler;

View File

@ -0,0 +1,25 @@
/*
* Author: PabstMirror
* Recieves a possible error code from FUNC(eventTargetFinish)
*
* Arguments:
* 0: caller (player) <OBJECT>
* 1: target <OBJECT>
* 2: error message <STRING>
*
* Return Value:
* None
*
* Example:
* [player1, player2, "Someting fucked up"] call ace_disarming_fnc_eventCallerFinish
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_3(_caller,_target,_errorMsg);
if (_caller != ACE_player) exitWith {};
systemChat format ["Debug-Caller: Disarm finished from [%1] with code [%2]", _target, _errorMsg];
diag_log text format ["[ACE_Disarming] %1 - eventCallerFinish: %2", time, _this];

View File

@ -0,0 +1,26 @@
/*
* Author: PabstMirror
* After FUNC(disarmDropItems) has completed, passing a possible error code.
* Passes that error back to orginal caller.
*
* Arguments:
* 0: caller <OBJECT>
* 1: target <OBJECT>
* 2: errorMsg <STRING>
*
* Return Value:
* Nothing
*
* Example:
* [player1, player2, "Someting fucked up"] call ace_disarming_fnc_eventTargetFinish
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_3(_caller,_target,_errorMsg);
if (_errorMsg != "") then {
diag_log text format ["[ACE_Disarming] %1 - eventTargetFinish: %2", time, _this];
["DisarmDebugCallback", [_caller], [_caller, _target, _errorMsg]] call EFUNC(common,targetEvent);
};

View File

@ -0,0 +1,39 @@
/*
* Author: PabstMirror
* Disarm Event Handler, Starting func, called on the target.
* If target has to remove uniform/vest, this will add all uniform/vest items to the drop list.
*
* Arguments:
* 0: caller (player) <OBJECT>
* 1: target <OBJECT>
* 2: type of disarm <STRING>
*
* Return Value:
* Nothing
*
* Example:
* eventTargetStart
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_3(_caller,_target,_listOfObjectsToRemove);
_itemsToAdd = [];
{
if (_x == (uniform _target)) then {
_itemsToAdd = _itemsToAdd + (uniformItems _target);
};
if (_x == (vest _target)) then {
_itemsToAdd = _itemsToAdd + (vestItems _target);
};
} forEach _listOfObjectsToRemove;
{
if (!(_x in _listOfObjectsToRemove)) then {
_listOfObjectsToRemove pushBack _x;
};
} forEach _itemsToAdd;
[_caller, _target, _listOfObjectsToRemove] call FUNC(disarmDropItems);

View File

@ -0,0 +1,29 @@
/*
* Author: PabstMirror
* Helper function to get all gear of a container
*
* Arguments:
* 0: Container <OBJECT>
*
* Return Value:
* Array of 2 arrays, classnames and count<ARRAY>
*
* Example:
* [["ace_bandage"],[2]] = [box] call ace_disarming_fnc_getAllGearContainer
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_1(_target);
private ["_allGear"];
_allGear = [[],[]];
{
(_allGear select 0) append (_x select 0);
(_allGear select 1) append (_x select 1);
} forEach [(getWeaponCargo _target), (getItemCargo _target), (getMagazineCargo _target), (getBackpackCargo _target)];
_allGear

View File

@ -0,0 +1,52 @@
/*
* Author: PabstMirror
* Helper function to get all gear of a unit.
*
* Arguments:
* 0: Target <OBJECT>
*
* Return Value:
* Array of 2 arrays, classnames and count<ARRAY>
*
* Example:
* [["ace_bandage"],[2]] = [bob] call ace_disarming_fnc_getAllGearUnit
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_1(_target);
_allItems = ((weapons _target) + (magazines _target) + (items _target) + (assignedItems _target));
if ((backpack _target) != "") then {
_allItems pushBack (backpack _target);
};
if ((vest _target) != "") then {
_allItems pushBack (vest _target);
};
if ((uniform _target) != "") then {
_allItems pushBack (uniform _target);
};
if ((headgear _target) != "") then {
_allItems pushBack (headgear _target);
};
//What kind of asshole takes a man's glasses?
if ((goggles _target) != "") then {
_allItems pushBack (goggles _target);
};
_uniqueClassnames = [];
_classnamesCount = [];
//Filter unique and count
{
_index = _uniqueClassnames find _x;
if (_index != -1) then {
_classnamesCount set [_index, ((_classnamesCount select _index) + 1)];
} else {
_uniqueClassnames pushBack _x;
_classnamesCount pushBack 1;
};
} forEach _allItems;
[_uniqueClassnames, _classnamesCount]

View File

@ -0,0 +1,106 @@
/*
* Author: PabstMirror
* Opens the disarm dialog (allowing a person to remove items)
*
* Arguments:
* 0: Caller (player) <OBJECT>
* 1: Target <OBJECT>
*
* Return Value:
* None
*
* Example:
* [player, bob] call ace_disarming_fnc_openDisarmDialog
*
* Public: No
*/
#include "script_component.hpp"
#define TEXTURES_RANKS [ \
"", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\private_gs.paa", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\corporal_gs.paa", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\sergeant_gs.paa", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\lieutenant_gs.paa", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\captain_gs.paa", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\major_gs.paa", \
"\A3\Ui_f\data\GUI\Cfg\Ranks\colonel_gs.paa" \
]
PARAMS_2(_caller,_target);
//Sanity Checks
if (_caller != ACE_player) exitwith {ERROR("Player isn't caller?");};
if (!([_player, _target] call FUNC(canPlayerDisarmUnit))) exitWith {ERROR("Can't Disarm Unit");};
if (dialog) then {ERROR("Dialog open when trying to open disarm dialog"); closeDialog 0;};
disableSerialization;
createDialog QGVAR(remoteInventory);
_display = uiNamespace getVariable ["ACE_remoteInventory", displayNull];
if (isNull _display) exitWith {ERROR("Display is Null");};
GVAR(disarmTarget) = _target;
//Setup Drop Event (on right pannel)
(_display displayCtrl 632) ctrlAddEventHandler ["LBDrop", {
if (isNull GVAR(disarmTarget)) exitWith {};
PARAMS_5(_ctrl,_xPos,_yPos,_idc,_itemInfo);
EXPLODE_3_PVT((_itemInfo select 0),_displayText,_value,_data);
if (isNull GVAR(disarmTarget)) exitWith {ERROR("disarmTarget is null");};
TRACE_2("Debug: Droping %1 from %2",_data,GVAR(disarmTarget));
["DisarmDropItems", [GVAR(disarmTarget)], [ACE_player, GVAR(disarmTarget), [_data]]] call EFUNC(common,targetEvent);
false //not sure what this does
}];
//Setup PFEH
[{
disableSerialization;
EXPLODE_2_PVT(_this,_args,_pfID);
EXPLODE_3_PVT(_args,_player,_target,_display);
if ((!([_player, _target] call FUNC(canPlayerDisarmUnit))) ||
{isNull _display} ||
{_player != ACE_player}) then {
[_pfID] call CBA_fnc_removePerFrameHandler;
GVAR(disarmTarget) = objNull;
if (!isNull _display) then {closeDialog 0;}; //close dialog if still open
} else {
_groundContainer = _display displayCtrl 632;
_targetContainer = _display displayCtrl 633;
_playerName = _display displayCtrl 111;
_rankPicture = _display displayCtrl 1203;
//Show rank and name (just like BIS's inventory)
_rankIndex = ((["PRIVATE", "CORPORAL", "SERGEANT", "LIEUTENANT", "CAPTAIN", "MAJOR", "COLONEL"] find (rank _target)) + 1);
_rankPicture ctrlSetText (TEXTURES_RANKS select _rankIndex);
_playerName ctrlSetText ([GVAR(disarmTarget)] call EFUNC(common,getName));
//Clear both inventory lists:
lbClear _groundContainer;
lbClear _targetContainer;
//Show the items in the ground disarmTarget's inventory
_targetUniqueItems = [GVAR(disarmTarget)] call FUNC(getAllGearUnit);
[_targetContainer, _targetUniqueItems] call FUNC(showItemsInListbox);
//Try to find a holder that the target is using to drop items into:
_holder = objNull;
{
if ((_x getVariable [QGVAR(disarmUnit), objNull]) == _target) exitWith {
_holder = _x;
};
} forEach ((getpos _target) nearObjects [DISARM_CONTAINER, 3]);
//If a holder exists, show it's inventory
if (!isNull _holder) then {
_holderUniqueItems = [_holder] call FUNC(getAllGearContainer);
[_groundContainer, _holderUniqueItems] call FUNC(showItemsInListbox);
};
};
}, 0, [_caller, _target, _display]] call CBA_fnc_addPerFrameHandler;

View File

@ -0,0 +1,60 @@
/*
* Author: PabstMirror
* Shows a list of inventory items in a listBox control.
*
* Arguments:
* 0: RscListBox <CONTROL>
* 1: ItemArray [["itemClassnames"],[counts]] <ARRAY>
*
* Return Value:
* Nothing
*
* Example:
* [theListBox, [["ace_bandage"],[2]]] call ace_disarming_fnc_showItemsInListbox
*
* Public: No
*/
#include "script_component.hpp"
disableSerialization;
PARAMS_2(_listBoxCtrl,_itemsCountArray);
private "_classname";
{
_displayName = "";
_picture = "";
_classname = _x;
_count = (_itemsCountArray select 1) select _forEachIndex;
if (_classname != DUMMY_ITEM) then { //Don't show the dummy potato
switch (true) do {
case (isClass (configFile >> "CfgWeapons" >> _classname)): {
_displayName = getText (configFile >> "CfgWeapons" >> _classname >> "displayName");
_picture = getText (configFile >> "CfgWeapons" >> _classname >> "picture");
};
case (isClass (configFile >> "CfgMagazines" >> _classname)): {
_displayName = getText (configFile >> "CfgMagazines" >> _classname >> "displayName");
_picture = getText (configFile >> "CfgMagazines" >> _classname >> "picture");
};
case (isClass (configFile >> "CfgVehicles" >> _classname)): {
_displayName = getText (configFile >> "CfgVehicles" >> _classname >> "displayName");
_picture = getText (configFile >> "CfgVehicles" >> _classname >> "picture");
};
case (isClass (configFile >> "CfgGlasses" >> _classname)): {
_displayName = getText (configFile >> "CfgGlasses" >> _classname >> "displayName");
_picture = getText (configFile >> "CfgGlasses" >> _classname >> "picture");
};
default {
ERROR(format ["[%1] - bad classname", _classname]);
};
};
_listBoxCtrl lbAdd format ["%1", _displayName];
_listBoxCtrl lbSetData [_forEachIndex, _classname];
_listBoxCtrl lbSetPicture [_forEachIndex, _picture];
_listBoxCtrl lbSetTextRight [_forEachIndex, str _count];
};
} forEach (_itemsCountArray select 0);

View File

@ -0,0 +1,41 @@
/*
* Author: PabstMirror
* Verifies magazines moved with exact ammo counts preserved.
* Arrays will be in format from magazinesAmmo/magazinesAmmoCargo
* e.g.: [["30Rnd_65x39_caseless_mag",15], ["30Rnd_65x39_caseless_mag",30]]
*
* Arguments:
* 0: Start on container A <ARRAY>
* 1: End on container A <ARRAY>
* 2: Start on container B <ARRAY>
* 3: End on container B <ARRAY>
*
* Return Value:
* Verified Good <BOOL>
*
* Example:
* [stuff] call ace_disarming_fnc_verifyMagazinesMoved
*
* Public: No
*/
#include "script_component.hpp"
private ["_problem", "_beginingArray"];
PARAMS_4(_startA,_endA,_startB,_endB);
//Quick Lazy Count Check
if (((count _startA) + (count _startB)) != ((count _endA) + (count _endB))) exitWith {
false
};
_beginingArray = (_startA + _startB);
_problem = false;
{
_index = _beginingArray find _x;
if (_index == -1) exitWith {_problem = true;};
_beginingArray deleteAt _index;
} forEach (_endA + _endB);
(!_problem) && {_beginingArray isEqualTo []}

View File

@ -0,0 +1 @@
#include "\z\ace\addons\disarming\script_component.hpp"

View File

@ -0,0 +1,162 @@
//The disarming dialog
//Meant to mimic the real BIS inventory (so people understand how to use it)
class RscText;
class RscPicture;
class RscActiveText;
class RscListBox;
//Use the definese from
#define X_BIS(num) (num * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2))
#define Y_BIS(num) (num * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2))
#define W_BIS(num) (num * (((safezoneW / safezoneH) min 1.2) / 40))
#define H_BIS(num) (num * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25))
#define X_MAKEITBIGGA(num) (num * (safeZoneH / 40) + (safezoneX + (safezoneW - safeZoneH)/2))
#define Y_MAKEITBIGGA(num) (num * (safeZoneH / 30) + (safezoneY + (safezoneH - (safeZoneH / 1.2))/2))
#define W_MAKEITBIGGA(num) (num * (safeZoneH / 40))
#define H_MAKEITBIGGA(num) (num * (safeZoneH / 30))
#define X_PART(num) QUOTE(linearConversion [ARR_5(0, 2, (missionNamespace getVariable [ARR_2(QUOTE(QEGVAR(inventory,inventoryDisplaySize)), 0)]), X_BIS(num), X_MAKEITBIGGA(num))])
#define Y_PART(num) QUOTE(linearConversion [ARR_5(0, 2, (missionNamespace getVariable [ARR_2(QUOTE(QEGVAR(inventory,inventoryDisplaySize)), 0)]), Y_BIS(num), Y_MAKEITBIGGA(num))])
#define W_PART(num) QUOTE(linearConversion [ARR_5(0, 2, (missionNamespace getVariable [ARR_2(QUOTE(QEGVAR(inventory,inventoryDisplaySize)), 0)]), W_BIS(num), W_MAKEITBIGGA(num))])
#define H_PART(num) QUOTE(linearConversion [ARR_5(0, 2, (missionNamespace getVariable [ARR_2(QUOTE(QEGVAR(inventory,inventoryDisplaySize)), 0)]), H_BIS(num), H_MAKEITBIGGA(num))])
class GVAR(remoteInventory) {
idd = -1;
movingEnable = 0;
enableSimulation = 1;
enableDisplay = 1;
onLoad = "uiNamespace setVariable ['ACE_remoteInventory', _this select 0];";
duration = 2147483647;
fadein = 0;
fadeout = 0;
class Colors {
dragValidBgr[] = {"(profilenamespace getvariable ['IGUI_TEXT_RGB_R',0])","(profilenamespace getvariable ['IGUI_TEXT_RGB_G',1])","(profilenamespace getvariable ['IGUI_TEXT_RGB_B',1])",0.5};
dragInvalidBgr[] = {"(profilenamespace getvariable ['IGUI_ERROR_RGB_R',0.8])","(profilenamespace getvariable ['IGUI_ERROR_RGB_G',0.0])","(profilenamespace getvariable ['IGUI_ERROR_RGB_B',0.0])",0.5};
dragValidBar[] = {"(profilenamespace getvariable ['IGUI_WARNING_RGB_R',0.8])","(profilenamespace getvariable ['IGUI_WARNING_RGB_G',0.5])","(profilenamespace getvariable ['IGUI_WARNING_RGB_B',0.0])",0.5};
dragInvalidBar[] = {"(profilenamespace getvariable ['IGUI_ERROR_RGB_R',0.8])","(profilenamespace getvariable ['IGUI_ERROR_RGB_G',0.0])","(profilenamespace getvariable ['IGUI_ERROR_RGB_B',0.0])",0.5};
progressBar[] = {"(profilenamespace getvariable ['IGUI_TEXT_RGB_R',0])","(profilenamespace getvariable ['IGUI_TEXT_RGB_G',1])","(profilenamespace getvariable ['IGUI_TEXT_RGB_B',1])",1};
progressBarBgr[] = {"(profilenamespace getvariable ['IGUI_BCG_RGB_R',0])","(profilenamespace getvariable ['IGUI_BCG_RGB_G',1])","(profilenamespace getvariable ['IGUI_BCG_RGB_B',1])",0.75};
highlight[] = {"(profilenamespace getvariable ['IGUI_TEXT_RGB_R',0])","(profilenamespace getvariable ['IGUI_TEXT_RGB_G',1])","(profilenamespace getvariable ['IGUI_TEXT_RGB_B',1])",0.5};
};
class controlsBackground {};
class controls {
class CA_ContainerBackground: RscText {
idc = -1;
x = X_PART(1);
y = Y_PART(1);
w = W_PART(12);
h = H_PART(22.5);
colorBackground[] = {0.05,0.05,0.05,0.7};
};
class CA_PlayerBackground: RscText {
idc = -1;
x = X_PART(14.6);
y = Y_PART(2);
w = W_PART(24.4);
h = H_PART(21.5);
colorBackground[] = {0.05,0.05,0.05,0.7};
};
class TitleBackground: RscText {
idc = -1;
x = X_PART(14.6);
y = Y_PART(1);
w = W_PART(24.4);
h = H_PART(1);
colorBackground[] = {0.1,0.1,0.1,1};
};
class PlayersName: RscText {
idc = 111;
// text = "Player name here:";
x = X_PART(15.6);
y = Y_PART(1);
w = W_PART(19.8);
h = H_PART(1);
};
class RankBackground: RscText {
idc = -1;
x = X_PART(15.1);
y = Y_PART(1.25);
w = W_PART(0.6);
h = H_PART(0.6);
colorBackground[] = {1,1,1,0.2};
};
class RankPicture: RscPicture {
idc = 1203;
// text = "\A3\Ui_f\data\GUI\Cfg\Ranks\corporal_gs.paa";
x = X_PART(15.1);
y = Y_PART(1.25);
w = W_PART(0.6);
h = H_PART(0.6);
};
class ButtonBack: RscActiveText {
idc = -1;
style = 48;
color[] = {1,1,1,0.7};
text = "\A3\Ui_f\data\GUI\Rsc\RscDisplayArcadeMap\icon_exit_cross_ca.paa";
x = X_PART(38);
y = Y_PART(1);
w = W_PART(1);
h = H_PART(1);
colorText[] = {1,1,1,0.7};
colorActive[] = {1,1,1,1};
tooltip = "$STR_DISP_OPT_CLOSE";
onButtonClick = "closeDialog 0";
};
class ExternalContainerBackground: RscPicture {
colorText[] = {1,1,1,0.1};
idc = -1;
x = X_PART(1.5);
y = Y_PART(3.7);
w = W_PART(11);
h = H_PART(18.4);
};
class PlayerContainerBackground: ExternalContainerBackground {
idc = -1;
x = X_PART(15.1);
y = Y_PART(6);
w = W_PART(11);
h = H_PART(14);
};
class GroundTitleBackground: RscText {
idc = -1;
x = X_PART(1);
y = Y_PART(1);
w = W_PART(12);
h = H_PART(1);
colorBackground[] = {0.1,0.1,0.1,1};
};
class GroundName: RscText {
idc = -1;
text = "$STR_cfgVehicles_WeaponHolder0"; //"ground"
x = X_PART(1);
y = Y_PART(1);
w = W_PART(12);
h = H_PART(1);
};
class GroundContainer: RscListBox {
idc = 632;
sizeEx = "0.8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
sizeEx2 = "0.8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
rowHeight = "1.75 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
canDrag = 0;
colorText[] = {1,1,1,1};
colorBackground[] = {0,0,0,0};
itemBackground[] = {1,1,1,0.2};
itemSpacing = 0.001;
x = X_PART(1.5);
y = Y_PART(2.5);
w = W_PART(11);
h = H_PART(21);
};
class UniformContainer: GroundContainer {
idc = 633;
canDrag = 1;
x = X_PART(15.1);
};
};
};

View File

@ -0,0 +1,16 @@
#define COMPONENT disarming
#include "\z\ace\addons\main\script_mod.hpp"
#ifdef DEBUG_ENABLED_DISARMING
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_DISARMING
#define DEBUG_SETTINGS DEBUG_SETTINGS_DISARMING
#endif
#include "\z\ace\addons\main\script_macros.hpp"
#define DISARM_CONTAINER "GroundWeaponHolder"
#define DUMMY_ITEM "ACE_DebugPotato"
#define UNIQUE_MAGAZINES ["ACE_key_customKeyMagazine"]

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Edited with tabler - 2015-03-17 -->
<Project name="ACE">
<Package name="Disarming">
<Key ID="STR_ACE_Disarming_OpenInventory">
<English>Open Inventory</English>
</Key>
</Package>
</Project>