Add realistic 9m14 behaviour

the 9m14 control joystick can attach 4 9m14 launchers at a time. Replicate that here
This commit is contained in:
Brandon Danyluk 2021-05-08 02:48:40 -06:00
parent 8b3e90925e
commit fc7b310529
26 changed files with 646 additions and 13 deletions

View File

@ -2,6 +2,13 @@ class CfgAmmo {
class M_Scalpel_AT;
class ammo_Penetrator_Base;
class GVAR(9s415_dummy_ammo): M_Scalpel_AT {
aiAmmoUsageFlags = 0;
model = "";
proxyShape = "";
effectsMissile = "";
};
class GVAR(9m14_penetrator): ammo_Penetrator_Base {
caliber = 60;
warheadName = "HEAT";
@ -46,11 +53,13 @@ class CfgAmmo {
class ace_missileguidance {
enabled = 1;
pitchRate = 5; // Minium flap deflection for guidance
yawRate = 5; // Maximum flap deflection for guidance
pitchRate = 15; // Minium flap deflection for guidance
yawRate = 15; // Maximum flap deflection for guidance
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
showTrail = 1;
// Guidance type for munitions
defaultSeekerType = "MCLOS";
seekerTypes[] = { "MCLOS" };
@ -61,7 +70,7 @@ class CfgAmmo {
defaultNavigationType = "Line";
navigationTypes[] = { "Line" };
lineGainP = 1;
lineGainP = 5;
lineGainD = 0;
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]

View File

@ -8,5 +8,13 @@ class CfgMagazines {
displayNameShort = CSTRING(9m14_missile);
descriptionShort = CSTRING(9m14_missile_descriptionShort);
};
class GVAR(9s415_dummy): 12Rnd_PG_missiles {
count = 4;
ammo = QGVAR(9s415_dummy_ammo);
displayName = CSTRING(9m14_missile);
displayNameShort = CSTRING(9m14_missile);
descriptionShort = CSTRING(9m14_missile_descriptionShort);
};
};

View File

@ -92,6 +92,38 @@ class CfgVehicles {
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
displayName = CSTRING(9m14);
class GVAR(takePlug) {
displayName = CSTRING(takePlug);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakePlug));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(takePlug));
};
};
};
};
class ThingX;
class GVAR(plug): ThingX {
displayName = QGVAR(plug);
scope = 1;
scopeCurator = 1;
model = "\a3\Structures_F_Orange\VR\Helpers\Sign_sphere10cm_Geometry_F.p3d";
destrType = "DestructNo";
class ACE_Actions {
class ACE_MainActions {
displayName = CSTRING(plug);
condition = "true";
distance = 2;
class GVAR(pickup) {
displayName = CSTRING(pickupPlug);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canPickupPlug));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(pickupPlug));
};
class GVAR(unattach) {
displayName = CSTRING(unattachPlug);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canUnattachPlug));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(unattachPlug));
};
};
};
};
@ -102,6 +134,7 @@ class CfgVehicles {
faction = "BLU_F";
crew = "B_Soldier_F";
author = "Brandon (TCVM)";
ace_missileguidance_hasMCLOSControl = 1;
displayName = CSTRING(9s415);
model = QPATHTOF(data\9m14_joystick.p3d);
picture = "\A3\Static_F_Gamma\data\UI\gear_StaticTurret_AT_CA.paa";
@ -131,13 +164,13 @@ class CfgVehicles {
class MainTurret: MainTurret {
optics = 1;
turretInfoType = "RscWeaponEmpty";
gunnerOpticsModel = "";
gunnerOpticsModel = "\a3\weapons_f_gamma\reticle\GMG_01_Optics_Gunner_F";
minElev = 0;
maxElev = 0;
weapons[] = { QGVAR(9s415_dummy) };
weapons[] = { QGVAR(9s415_dummy_weapon) };
magazines[] = { QGVAR(9s415_dummy) };
gunnerAction = "";
gunnerAction = "gunner_static_low01";
gunnergetInAction = "";
gunnergetOutAction = "";
@ -159,11 +192,11 @@ class CfgVehicles {
visionMode[] = {"Normal"};
thermalMode[] = {0};
};
gunnerRightHandAnimName = "";
gunnerLeftHandAnimName = "";
gunBeg = "";
gunEnd = "";
memoryPointGunnerOptics = "";
gunnerRightHandAnimName = "OtocHlaven_shake";
gunnerLeftHandAnimName = "OtocHlaven_shake";
gunBeg = "spice rakety";
gunEnd = "konec rakety";
memoryPointGunnerOptics = "view_pos";
};
};

View File

@ -1,7 +1,6 @@
class CfgWeapons {
class MissileLauncher;
class GVAR(9m14): MissileLauncher {
scope = 2;
displayName = CSTRING(9m14_missile);
magazines[] = { QGVAR(9m14) };
initSpeed = 100;
@ -25,5 +24,31 @@ class CfgWeapons {
autoReload = 1;
magazineReloadTime = 20;
};
// dummy weapon meant to allow the ability to shoot "connected" malyutkas
class GVAR(9s415_dummy_weapon): MissileLauncher {
displayName = CSTRING(9m14_missile); // intended to be 9m14
magazines[] = { QGVAR(9s415_dummy) };
initSpeed = 100;
autoFire = 0;
canLock = 0;
weaponLockSystem = 0;
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
soundFly[] = {"",1,1.1,700};
nameSound = "";
sounds[] = {""};
class StandardSound {
begin1[] = {"",1.12202,1.3,1000};
soundBegin[] = {"",1};
soundsetshot[] = {""};
};
cursor = "EmptyCursor";
cursorAim = "missile";
showAimCursorInternal = 0;
autoReload = 1;
magazineReloadTime = 0.2;
};
};

View File

@ -0,0 +1,16 @@
PREP(canAttachPlug);
PREP(attachPlug);
PREP(canPickupPlug);
PREP(pickupPlug);
PREP(canTakePlug);
PREP(takePlug);
PREP(canUnattachPlug);
PREP(unattachPlug);
PREP(onFired);
PREP(initSuitcase);
PREP(initJoystick);
PREP(carryPlugPFH);
PREP(onMouseButtonDown);
PREP(returnPlug);
PREP(onLauncherFired);

View File

@ -1,2 +1,27 @@
#include "script_component.hpp"
[QGVAR(9m14_joystick), "fired", LINKFUNC(onFired)] call CBA_fnc_addClassEventHandler;
[QGVAR(9m14), "fired", LINKFUNC(onLauncherFired)] call CBA_fnc_addClassEventHandler;
[QGVAR(9m14_joystick), "init", LINKFUNC(initJoystick), true, [], true] call CBA_fnc_addClassEventHandler;
[QGVAR(9m14), "init", LINKFUNC(initSuitcase), true, [], true] call CBA_fnc_addClassEventHandler;
["MouseButtonDown", LINKFUNC(onMouseButtonDown)] call CBA_fnc_addDisplayHandler;
if (hasInterface) then {
["vehicle", {
params ["_unit","_vehicle"];
TRACE_2("vehicle change",_vehicle,typeOf _vehicle);
if (!(_vehicle isKindOf QGVAR(9m14_joystick))) exitWith {};
// transfer locality of connected units
private _connectedUnits = _vehicle getVariable QGVAR(plugStatus);
{
if (_x isNotEqualTo objNull) then {
["ace_setOwner", [_x, clientOwner]] call CBA_fnc_serverEvent;
_x setVariable [QGVAR(owner), _unit];
};
} forEach _connectedUnits;
}, true] call CBA_fnc_addPlayerEventHandler;
};

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,49 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Attaches a launch suitcase to a control box
*
* Arguments:
* 0: Suitcase <OBJECT>
* 1: Control Box <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, obj2] call ace_malyutka_fnc_attachPlug
*
* Public: No
*/
params ["_suitcase", "_controlBox"];
private _statuses = _controlBox getVariable QGVAR(plugStatus);
private _availableIndex = _statuses findIf { _x isEqualTo objNull };
if (_availableIndex >= 0) then {
_statuses set [_availableIndex, _suitcase];
_controlBox setVariable [QGVAR(plugStatus), _statuses, true];
private _plug = _suitcase getVariable QGVAR(plugHeader);
_plug attachTo [_controlBox, [0, 0, 0], format ["plug_%1", _availableIndex + 1]];
_plug setVariable [QGVAR(attachedControlBox), _controlBox, true];
_suitcase setVariable [QGVAR(attachedToPlugNumber), _availableIndex, true];
if (someAmmo _suitcase) then {
private _currentAmmoState = (_controlBox getVariable QGVAR(vehicleAmmo)) + 1;
_controlBox setVariable [QGVAR(vehicleAmmo), _currentAmmoState, true];
// can only hold 4 missiles at a time, so we multiply by 1/4 to get correct ammo
_controlBox setVehicleAmmo (_currentAmmoState * 0.25);
};
// transfer locality so missileguidance works
if !(local gunner _controlBox) then {
private _gunnerID = ((gunner _controlBox) getVariable [QEGVAR(common,playerOwner), CBA_clientID]);
["ace_setOwner", [_suitcase, _gunnerID]] call CBA_fnc_serverEvent;
_suitcase setVariable [QGVAR(owner), _unit];
};
} else {
// how did we get here?
WARNING_2("Managed to attach plug to a full control box",_availableIndex,_statuses);
};

View File

@ -0,0 +1,22 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Whether or not we can attach the plug to a control box
*
* Arguments:
* 0: Suitcase <OBJECT>
* 1: Control Box <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_canAttachPlug
*
* Public: No
*/
params ["_suitcase", "_controlBox"];
private _statuses = _controlBox getVariable QGVAR(plugStatus);
// if we have a single available plug, we can attach
(_statuses findIf { _x isEqualTo objNull }) >= 0

View File

@ -0,0 +1,20 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Whether or not we can pickup the plug from the ground
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Plug <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_canPickupPlug
*
* Public: No
*/
params ["", "_plug"];
(objNull isEqualTo attachedTo _plug) && { (_plug getVariable QGVAR(attachedControlBox)) isEqualTo objNull }

View File

@ -0,0 +1,20 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Whether or not we can take the plug from the launch suitcase
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_canTakePlug
*
* Public: No
*/
params ["_unit", "_target"];
(alive _target) && !(_target getVariable QGVAR(plugTaken))

View File

@ -0,0 +1,20 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Whether or not we can unattach the plug from the control box
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_canUnattachPlug
*
* Public: No
*/
params ["", "_plug"];
(_plug getVariable QGVAR(attachedControlBox)) isNotEqualTo objNull

View File

@ -0,0 +1,80 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Handles carrying of plug
*
* Arguments:
* 0: Unit carrying plug <OBJECT>
* 1: Plug <OBJECT>
*
* Return Value:
* None
*
* Example:
* [player, plug] call ace_malyutka_fnc_carryPlugPFH
*
* Public: No
*/
params ["_unit", "_plug"];
private _originSuitcase = _plug getVariable QGVAR(origin);
private _rope = _originSuitcase getVariable QGVAR(plugRope);
[{
params ["_args", "_handle"];
_args params ["_unit", "_rope", "_plug", "_suitcase"];
private _exitCondition = !(
!isNull _plug
&& !isNull _suitcase
&& { alive _unit }
&& {"" isEqualTo currentWeapon _unit || {_unit call EFUNC(common,isSwimming)}}
&& {[_unit, objNull, ["isNotInside", "isNotOnLadder", "isNotSwimming", "notOnMap"]] call EFUNC(common,canInteractWith)}
&& {"unconscious" isNotEqualTo toLower animationState _unit}
&& {!(_unit getVariable ["ACE_isUnconscious", false])}
);
if (_plug isNotEqualTo objNull && _suitcase isNotEqualTo objNull) then {
_exitCondition = _exitCondition || (_plug getVariable QGVAR(dropped));
_exitCondition = _exitCondition || ((_plug distance2d _suitcase) > MAX_WIRE_DISTANCE);
};
if (_exitCondition) exitWith {
[_handle] call CBA_fnc_removePerFrameHandler;
call EFUNC(interaction,hideMouseHint);
_unit setVariable [QGVAR(hint), []];
_unit setVariable [QGVAR(carryingPlug), objNull];
if ((_plug getVariable QGVAR(attachedControlBox)) isEqualTo objNull) then {
detach _plug;
};
_plug setVariable [QGVAR(dropped), false];
};
private _hintLMB = "";
private _hintRMB = localize ELSTRING(dragging,Drop);
getCursorObjectParams params ["_cursorObject", "", "_distance"];
if (!isNull _cursorObject && {_distance < ATTACH_DISTANCE}) then {
if (
_cursorObject isKindOf QGVAR(9m14_joystick) &&
{ ([_suitcase, _cursorObject] call FUNC(canAttachPlug)) }
) then {
_hintLMB = localize LSTRING(attachPlug);
};
if (
_cursorObject isKindOf QGVAR(9m14) &&
{ _cursorObject isEqualTo (_plug getVariable QGVAR(origin)) }
) then {
_hintLMB = localize LSTRING(returnPlug);
};
};
private _hint = [_hintLMB, _hintRMB];
if (_hint isNotEqualTo (_unit getVariable [QGVAR(hint), []])) then {
_unit setVariable [QGVAR(hint), _hint];
_hint call EFUNC(interaction,showMouseHint);
};
}, 0, [_unit, _rope, _plug, _originSuitcase]] call CBA_fnc_addPerFrameHandler;

View File

@ -0,0 +1,25 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Initialise joystick
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_initJoystick
*
* Public: No
*/
params ["_joystick"];
// each plug has information regarding the current launcher which is connected
// if null, no launcher is connected
_joystick setVariable [QGVAR(plugStatus), [objNull, objNull, objNull, objNull], true];
_joystick setVariable [QGVAR(vehicleAmmo), 0, true];
_joystick setVehicleAmmo 0;

View File

@ -0,0 +1,24 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Initialise suitcase launcher
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_initSuitcase
*
* Public: No
*/
params ["_suitcase"];
_suitcase setVariable [QGVAR(plugTaken), false, true];
_suitcase setVariable [QGVAR(plugRope), objNull, true];
_suitcase setVariable [QGVAR(plugHeader), objNull, true];
_suitcase setVariable [QGVAR(attachedToPlugNumber), -1, true];

View File

@ -0,0 +1,37 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Handle the firing of a Malyutka
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_onFired
*
* Public: No
*/
params ["_unit", "", "", "", "", "", "_projectile"];
// projectile is a dummy to trigger this event handler
deleteVehicle _projectile;
private _controlBox = vehicle _unit;
private _currentAmmoState = (_controlBox getVariable QGVAR(vehicleAmmo));
_controlBox setVariable [QGVAR(vehicleAmmo), _currentAmmoState - 1, true];
private _statuses = _controlBox getVariable QGVAR(plugStatus);
private _availableIndex = _statuses findIf { (_x isNotEqualTo objNull) && (someAmmo _x) };
if (_availableIndex >= 0) then {
private _malyutka = _statuses select _availableIndex;
[_malyutka, QGVAR(9m14)] call BIS_fnc_fire;
} else {
// how did we get here?
private _statusesData = _statuses apply { (_x isNotEqualTo objNull) && (someAmmo _x) };
WARNING_3("Managed to fire when no control boxes were ready to fire",_availableIndex,_statuses,_statusesData);
};

View File

@ -0,0 +1,34 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Add a per frame handler to the malyutka that copies MCLOS control data from player to missile
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_onLauncherFired
*
* Public: No
*/
params ["_unit", "", "", "", "", "", "_projectile"];
[{
params ["_args", "_handle"];
_args params ["_unit", "_projectile"];
if !(alive _projectile) exitWith {
[_handle] call CBA_fnc_removePerFrameHandler;
};
// owner can change while missile is in flight
private _owner = _unit getVariable QGVAR(owner);
if ((vehicle _owner) isKindOf QGVAR(9m14_joystick)) then {
_unit setVariable [QEGVAR(missileguidance,MCLOS_direction), _owner getVariable [QEGVAR(missileguidance,MCLOS_direction), [0, 0, 0]]];
};
}, 0, [_unit, _projectile, _trackerLight]] call CBA_fnc_addPerFrameHandler;

View File

@ -0,0 +1,48 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Handles mouse interaction when carrying plug
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [player, plug] call ace_malyutka_fnc_onMouseButtonDown
*
* Public: No
*/
params ["", "_button"];
private _unit = ACE_PLAYER;
private _plug = _unit getVariable [QGVAR(carryingPlug), objNull];
if (_button > 1 || _plug isEqualTo objNull) exitWith {
};
if (_button == 1) then {
// RMB
_plug setVariable [QGVAR(dropped), true];
} else {
// LMB
getCursorObjectParams params ["_cursorObject", "", "_distance"];
if (!isNull _cursorObject && {_distance < ATTACH_DISTANCE}) then {
if (
_cursorObject isKindOf QGVAR(9m14_joystick) &&
{ ([_suitcase, _cursorObject] call FUNC(canAttachPlug)) }
) then {
[_plug getVariable QGVAR(origin), _cursorObject] call FUNC(attachPlug);
_plug setVariable [QGVAR(dropped), true];
};
if (
_cursorObject isKindOf QGVAR(9m14) &&
{ _cursorObject isEqualTo (_plug getVariable QGVAR(origin)) }
) then {
[_plug, _cursorObject] call FUNC(returnPlug);
};
};
};

View File

@ -0,0 +1,26 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Picks up plug from ground
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_pickupPlug
*
* Public: No
*/
params ["_unit", "_handle"];
_handle attachTo [_unit, [0, 1, 0], "pelvis"];
_unit setVariable [QGVAR(carryingPlug), _handle];
_plug setVariable [QGVAR(dropped), false];
[_unit] call EFUNC(weaponselect,putWeaponAway);
[_unit, _handle] call FUNC(carryPlugPFH);

View File

@ -0,0 +1,28 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Returns plug to launcher suitcase
*
* Arguments:
* 0: Plug <OBJECT>
* 1: Suitcase <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_returnPlug
*
* Public: No
*/
params ["_plug", "_suitcase"];
deleteVehicle _plug;
private _rope = _suitcase getVariable QGVAR(plugRope);
ropeDestroy _rope;
_suitcase setVariable [QGVAR(plugTaken), false, true];
_suitcase setVariable [QGVAR(plugRope), objNull, true];
_suitcase setVariable [QGVAR(plugHeader), objNull, true];

View File

@ -0,0 +1,32 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Takes a plug from the launch suitcase
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Suitcase <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_takePlug
*
* Public: No
*/
params ["_unit", "_target"];
private _handle = createVehicle [QGVAR(plug), [0, 0, 0], [], 0, "CAN_COLLIDE"];
_handle setVariable [QGVAR(origin), _target, true];
_handle setVariable [QGVAR(attachedControlBox), objNull, true];
_handle setVariable [QGVAR(dropped), false, false];
[_unit, _handle] call FUNC(pickupPlug);
private _rope = ropeCreate [_target, "missile_plug", _handle, [0, 0, 0], MAX_WIRE_DISTANCE];
_target setVariable [QGVAR(plugTaken), true, true];
_target setVariable [QGVAR(plugRope), _rope, true];
_target setVariable [QGVAR(plugHeader), _handle, true];

View File

@ -0,0 +1,35 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Unattaches plug from control box
*
* Arguments:
* 0: Static Weapon <OBJECT>
* 1: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject, player] call ace_malyutka_fnc_unattachPlug
*
* Public: No
*/
params ["_unit", "_plug"];
private _suitcase = _plug getVariable QGVAR(origin);
private _controlBox = _plug getVariable QGVAR(attachedControlBox);
private _suitcaseIndex = _suitcase getVariable QGVAR(attachedToPlugNumber);
if (_suitcaseIndex < 0) exitWith {
WARNING_1("Somehow unattached plug when not first attached",_suitcaseIndex);
};
_suitcase setVariable [QGVAR(attachedToPlugNumber), -1, true];
private _statuses = _controlBox getVariable QGVAR(plugStatus);
_statuses set [_suitcaseIndex, objNull];
_controlBox setVariable [QGVAR(plugStatus), _statuses, true];
_plug setVariable [QGVAR(attachedControlBox), objNull, true];
[_unit, _plug] call FUNC(pickupPlug);

View File

@ -3,7 +3,7 @@
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
#define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_MALYUTKA
@ -15,4 +15,6 @@
#endif
#include "\z\ace\addons\main\script_macros.hpp"
#define ATTACH_DISTANCE 3
#define MAX_WIRE_DISTANCE 15

View File

@ -16,5 +16,20 @@
<Key ID="STR_ACE_Malyutka_9s415">
<English>[CSW] 9S415 Control Unit</English>
</Key>
<Key ID="STR_ACE_Malyutka_takePlug">
<English>Take Plug</English>
</Key>
<Key ID="STR_ACE_Malyutka_attachPlug">
<English>Attach Plug</English>
</Key>
<Key ID="STR_ACE_Malyutka_plug">
<English>Plug</English>
</Key>
<Key ID="STR_ACE_Malyutka_pickupPlug">
<English>Pickup Plug</English>
</Key>
<Key ID="STR_ACE_Malyutka_returnPlug">
<English>Return Plug</English>
</Key>
</Package>
</Project>