Merge branch 'master' of github.com:KoffeinFlummi/ACE3

This commit is contained in:
esteldunedain 2015-04-11 11:12:56 -03:00
commit dec5aa3ec5
60 changed files with 1962 additions and 926 deletions

View File

@ -62,6 +62,7 @@ Raspu86
Riccardo Petricca <petriccarcc@gmail.com>
Robert Boklahánics <bokirobi@gmail.com>
simon84
Sniperwolf572 <tenga6@gmail.com>
Tonic
Tourorist <tourorist@gmail.com>
Valentin Torikian <valentin.torikian@gmail.com>

View File

@ -1,9 +1,7 @@
class CfgAmmo {
class BulletBase;
class B_20mm;
class ACE_20mm_HEDP : B_20mm {
class B_20mm : BulletBase {
hit = 80;
indirectHit = 12;
indirectHitRange = 2; //2;
@ -11,8 +9,22 @@ class CfgAmmo {
tracerStartTime = 0.02;
timeToLive = 40;
explosive = 1.8;
tracersEvery = 3;
tracerEndTime = 3.5;
CraterEffects = "ExploAmmoCrater";
explosionEffects = "ExploAmmoExplosion";
model = "\A3\Weapons_f\Data\bullettracer\tracer_red";
};
class ACE_20mm_HEDP : B_20mm {};
class ACE_20mm_AP : B_20mm {
hit = 50;
indirectHit = 12;
indirectHitRange = 0.3; //2;
explosive = 0;
CraterEffects = "";
explosionEffects = "";
};
// adjust minigun caliber and deflection to other ammo
class SubmunitionBullet;

View File

@ -2,7 +2,7 @@
class CfgPatches {
class ADDON {
units[] = {};
units[] = {"ACE_Comanche_Test"};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_common"};

View File

@ -15,7 +15,7 @@ class CfgWeapons {
class ACE_FakePrimaryWeapon: Rifle_Base_F {
scope = 2;
displayName = "";
model = "";
model = "\A3\Weapons_f\empty";
picture = "";
magazines[] = {"ACE_FakeMagazine"};
discreteDistance[] = {};

View File

@ -107,6 +107,7 @@ PREP(isAutoWind);
PREP(isAwake);
PREP(isEngineer);
PREP(isEOD);
PREP(isFeatureCameraActive);
PREP(isInBuilding);
PREP(isModLoaded);
PREP(isPlayer);
@ -177,6 +178,9 @@ PREP(useItem);
PREP(useMagazine);
PREP(waitAndExecute);
PREP(translateToWeaponSpace);
PREP(translateToModelSpace);
// config items
PREP(getConfigType);
PREP(getItemType);

View File

@ -1,23 +1,37 @@
/**
* fn_disableAI_f.sqf
* @Descr: N/A
* @Author: Glowbal
/*
* Author: Glowbal, KoffeinFlummi
* Disables/Enables AI
*
* @Arguments: []
* @Return:
* @PublicAPI: false
* Arguments:
* 0: Unit <OBJECT>
* 1: Disable AI <BOOL>
*
* Return Value:
* None
*
* Example:
* [bob, true] call ace_common_fnc_disableAI;
*
* Public: No
*/
#include "script_component.hpp"
private ["_unit","_disable"];
_unit = [_this, 0,ObjNull,[ObjNull]] call BIS_fnc_Param;
_disable = [_this, 1,false,[false]] call BIS_fnc_Param;
if (local _unit && !(IsPlayer _unit)) then {
PARAMS_2(_unit,_disable);
if ((local _unit) && {!([_unit] call EFUNC(common,isPlayer))}) then {
if (_disable) then {
_unit disableAI "Move";
_unit disableAI "MOVE";
_unit disableAI "TARGET";
_unit disableAI "AUTOTARGET";
_unit disableAI "FSM";
_unit disableConversation true;
} else {
_unit enableAI "Move";
//Sanity check to make sure we don't enable unconsious AI
if (_unit getVariable ["ace_isunconscious", false]) exitWith {ERROR("Enabling AI for unconsious unit");};
_unit enableAI "MOVE";
_unit enableAI "TARGET";
_unit enableAI "AUTOTARGET";
_unit enableAI "FSM";
_unit disableConversation false;
};
};
};

View File

@ -0,0 +1,31 @@
/*
* Author: Sniperwolf572
*
* Checks if one of the following BI feature cameras are active:
*
* - Classic camera (BIS_fnc_cameraOld)
* - Splendid camera (BIS_fnc_camera)
* - Arsenal camera (BIS_fnc_arsenal)
* - Animation viewer (BIS_fnc_animViewer)
* - Establishing shot (BIS_fnc_establishingShot)
*
* Arguments:
* None
*
* Return value:
* Is BI feature camera active (bool)
*
* Example:
* call ace_common_fnc_isFeatureCameraActive;
*
*/
#include "script_component.hpp"
(
!isNull (missionNamespace getVariable ["BIS_DEBUG_CAM", objNull]) || // Classic camera
{!isNull (missionNamespace getVariable ["BIS_fnc_camera_cam", objNull])} || // Splendid camera
{!isNull (uiNamespace getVariable ["BIS_fnc_arsenal_cam", objNull])} || // Arsenal camera
{!isNull (uiNamespace getVariable ["BIS_fnc_animViewer_cam", objNull])} || // Animation viewer camera
{!isNull (missionNamespace getVariable ["BIS_fnc_establishingShot_fakeUAV", objNull])} // Establishing shot camera
)

View File

@ -16,4 +16,5 @@
#include "script_component.hpp"
if (GVAR(showInThirdPerson)) exitWith { false };
(cameraView == "External")
(cameraView in ["EXTERNAL", "GROUP"] || {call EFUNC(common,isFeatureCameraActive)})

View File

@ -9,3 +9,11 @@ class Extended_PostInit_EventHandlers {
init = QUOTE(call COMPILE_FILE(XEH_post_init));
};
};
class Extended_Init_EventHandlers {
class LaserTargetBase {
class ADDON {
init = QUOTE(_this call DFUNC(laser_init));
};
};
};

View File

@ -14,13 +14,7 @@ PREP(translateToWeaponSpace);
PREP(laser_init);
GVAR(laser) = nil; // a single hud draws 1 laser at a time
PREP(laserTargetPFH);
ACE_LASERS = [];
ACE_DEFAULT_LASER_CODE = 1000;
ACE_DEFAULT_FIRE_SELECTION = [FIREMODE_DIRECT_LOAL, ACE_DEFAULT_LASER_CODE];
FUNC(getPosASL) = {visiblePositionASL (_this select 0)};
ACE_DEFAULT_LASER_CODE = 1001;

View File

@ -1,17 +1,21 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
private ["_missile", "_headingPitch", "_found", "_vectorTo", "_polarTo", "_dir", "_vertOk", "_horzOk", "_fov",
private ["_seeker", "_headingPitch", "_found", "_vectorTo", "_polarTo", "_dir", "_vertOk", "_horzOk", "_fov",
"_closestDistance", "_pos1", "_pos2", "_disCheck", "_currentTarget", "_potentialTargets", "_offset", "_vector"];
_missile = _this select 0;
_seeker = _this select 0;
_laserCode = _this select 1;
_fov = if (count _this > 2) then {_this select 2} else {75};
_vector = if (count _this > 3) then {_this select 3} else {vectorDir _missile};
_vector = if (count _this > 3) then {_this select 3} else {vectorDir _seeker};
_offset = if (count _this > 4) then {_this select 4} else {[0,0,0]};
_headingPitch = _vector call CBA_fnc_vect2polar;
_currentTarget = nil;
_found = false;
_getPosASL = {visiblePositionASL (_this select 0)};
LOG("Searching lasers");
if(!(isNil "ACE_LASERS")) then {
_potentialTargets = [];
@ -19,8 +23,8 @@ if(!(isNil "ACE_LASERS")) then {
{
if(!(isNull _x)) then {
_sensorPos = ATLtoASL(_missile modelToWorldVisual _offset);
_vectorTo = [_sensorPos, ([_x] call FUNC(getPosASL))] call BIS_fnc_vectorFromXToY;
_sensorPos = ATLtoASL(_seeker modelToWorldVisual _offset);
_vectorTo = [_sensorPos, ([_x] call _getPosASL)] call BIS_fnc_vectorFromXToY;
_polarTo = _vectorTo call CBA_fnc_vect2polar;
_dir = _polarTo select 1;
_dir = _dir - (_headingPitch select 1);
@ -42,7 +46,7 @@ if(!(isNil "ACE_LASERS")) then {
if(_vertOk && {_horzOk}) then {
// Does the laser currently have our current code, if we have one?
_targetCode = _x getVariable ["ACE_LASERTARGET_CODE", ACE_DEFAULT_LASER_CODE];
_targetCode = _x getVariable ["ACE_LASER_CODE", ACE_DEFAULT_LASER_CODE];
TRACE_1("Target in sight, checking code", _targetCode, _laserCode);
if(_targetCode == _laserCode) then {
_potentialTargets set[(count _potentialTargets), _x];
@ -56,11 +60,11 @@ if(!(isNil "ACE_LASERS")) then {
_closestDistance = 100000;
{
_pos1 = (getPosASL _missile);
_pos2 = ([_x] call FUNC(getPosASL));
_pos1 = (getPosASL _seeker);
_pos2 = ([_x] call _getPosASL);
_disCheck = _pos1 distance _pos2;
// shouldn't this bail out when a valid target is found instead of iterating over all potential targets ?
if(_disCheck < _closestDistance && {[_pos1, _pos2, _x, _missile] call FUNC(checkLos)}) then {
if(_disCheck < _closestDistance && {[_pos1, _pos2, _x, _seeker] call FUNC(checkLos)}) then {
_found = true;
_currentTarget = _x;
_closestDistance = _disCheck;

View File

@ -9,16 +9,16 @@ TRACE_1("enter", _this);
// Add the laser localized to the laser array, and give it the default localized code
PUSH(ACE_LASERS, _laserTarget);
// Check the vehicle, otherwise use the default
_laserTarget setVariable ["ACE_LASERTARGET_CODE", ACE_DEFAULT_LASER_CODE, false];
_laserTarget setVariable ["ACE_LASER_CODE", ACE_DEFAULT_LASER_CODE, false];
// Clean the lasers of any null objects while we are here
REM(ACE_LASERS, objNull);
if(!(local _laserTarget)) exitWith { };
// The target is local, so its on this client
if(!isDedicated) then {
_laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", player, true];
_laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", ACE_player, true];
[FUNC(laserTargetPFH), 0, [_laserTarget, player]] call cba_fnc_addPerFrameHandler;
[FUNC(laserTargetPFH), 0, [_laserTarget, ACE_player]] call cba_fnc_addPerFrameHandler;
} else {
// server side ownership of laser
//_laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", nil, false];

View File

@ -6,6 +6,6 @@ PREP(laserHudDesignateOff);
PREP(unitTurretHasDesignator);
GVAR(laser) = nil;
GVAR(laserActive) = false;
GVAR(active) = false;
FUNC(getPosASL) = {visiblePositionASL (_this select 0)};

View File

@ -28,7 +28,7 @@ GVAR(initializedClasses) = _initializedClasses;
if (getNumber (_turretConfig >> QGVAR(Enabled)) == 1) exitWith {
// @todo: Add the state variables to the vehicle, instead of to the client
// e.g.: _vehicle setVariable [format ["%1_%2", QGVAR(laserActive), _x], false];
// e.g.: _vehicle setVariable [format ["%1_%2", QGVAR(active), _x], false];
// Add actions
_onAction = [QGVAR(LaserOn), localize "STR_ACE_Laser_SelfDesignate_DesignatorOn", "",
@ -38,7 +38,7 @@ GVAR(initializedClasses) = _initializedClasses;
},
{
// Condition
!GVAR(laserActive) && {[ACE_player] call FUNC(unitTurretHasDesignator)}
!GVAR(active) && {[ACE_player] call FUNC(unitTurretHasDesignator)}
}] call EFUNC(interact_menu,createAction);
_offAction = [QGVAR(LaserOff), localize "STR_ACE_Laser_SelfDesignate_DesignatorOff", "",
@ -48,7 +48,7 @@ GVAR(initializedClasses) = _initializedClasses;
},
{
// Condition
GVAR(laserActive) && {[ACE_player] call FUNC(unitTurretHasDesignator)}
GVAR(active) && {[ACE_player] call FUNC(unitTurretHasDesignator)}
}] call EFUNC(interact_menu,createAction);
[_type, 1, ["ACE_SelfActions"], _onAction] call EFUNC(interact_menu,addActionToClass);

View File

@ -1,5 +1,11 @@
#include "script_component.hpp"
if( (count _this) > 2) then {
EXPLODE_3_PVT(_this,_vehicle,_shooter,_laserTarget);
// We got the optional vehicle list, clear the parameters
_vehicle setVariable[QGVAR(currentTarget), [], true];
};
if(isNil QGVAR(laser)) exitWith {
false
};
@ -15,6 +21,8 @@ if(!isNil "_handle") then {
REM(ACE_LASERS, GVAR(laser));
deleteVehicle GVAR(laser);
GVAR(laser) = nil;
GVAR(laserActive) = false;
GVAR(active) = false;
true

View File

@ -5,25 +5,21 @@ TRACE_1("enter", _this);
#define FCS_UPDATE_DELAY 1
FUNC(magnitude) = {
_this distance [0, 0, 0]
};
FUNC(mat_normalize3d) = {
private ["_mag"];
PARAMS_3(_vx,_vy,_vz);
_mag = _this call FUNC(magnitude);
if (_mag == 0) then {_mag = 1};
[(_vx/_mag), (_vy/_mag), (_vz/_mag)]
};
FUNC(laserHudDesignatePFH) = {
private["_args", "_laserTarget", "_shooter", "_vehicle", "_weapon", "_gunnerInfo", "_turret", "_pov", "_gunBeg", "_gunEnd", "_povPos", "_povDir", "_result", "_resultPositions", "_firstResult", "_forceUpdateTime"];
private["_strongestResultPos", "_args", "_laserTarget", "_shooter", "_vehicle", "_weapon", "_gunnerInfo", "_turret", "_pov", "_gunBeg", "_gunEnd", "_povPos", "_povDir", "_result", "_resultPositions", "_firstResult", "_forceUpdateTime"];
_args = _this select 0;
_laserTarget = _args select 0;
_shooter = _args select 1;
TRACE_1("", _args, (_laserTarget getVariable["ACE_LASER_CODE"]));
if((vehicle ACE_player) != _shooter || !alive _shooter || isNull _vehicle || isNull _laserTarget || !GVAR(active) ) exitWith {
[_vehicle, _shooter, _laserTarget] call FUNC(laserHudDesignateOff);
};
if(!([_shooter] call FUNC(unitTurretHasDesignator)) ) exitWith {
[_vehicle, _shooter, _laserTarget] call FUNC(laserHudDesignateOff);
};
if( (count _args) < 3) then {
_args set[2, diag_tickTime + FCS_UPDATE_DELAY];
};
@ -32,21 +28,23 @@ FUNC(laserHudDesignatePFH) = {
_vehicle = vehicle _shooter;
_weapon = currentWeapon _vehicle;
TRACE_1("", _args);
if(!alive _shooter || isNull _vehicle || isNull _laserTarget || !GVAR(laserActive) ) exitWith {
[] call FUNC(laserHudDesignateOff);
};
if(!([ACE_player] call FUNC(unitTurretHasDesignator)) ) exitWith {
[] call FUNC(laserHudDesignateOff);
};
// Retrieve the gunner and turret memory point information
_gunnerInfo = [_vehicle, _weapon] call CBA_fnc_getFirer;
_turretInfo = [_vehicle, _gunnerInfo select 1] call EFUNC(common,getTurretDirection);
_povPos = _turretInfo select 0;
_povDir = _turretInfo select 1;
_targetInfo = _vehicle getVariable[QGVAR(currentTarget), [] ];
if( (count _targetInfo) > 0) then {
if(_laserTarget != (_targetInfo select 0) ) then {
_targetInfo = []
};
};
if( (count _targetInfo) < 1) then {
_targetInfo = [_laserTarget, 1001]; // TODO: set laser code
_vehicle setVariable[QGVAR(currentTarget), _targetInfo, true];
_laserTarget setVariable[QGVAR(owner), _vehicle, true];
};
_result = [_povPos, _povDir] call EFUNC(laser,shootCone);
@ -54,24 +52,23 @@ FUNC(laserHudDesignatePFH) = {
_resultPositions = _result select 2;
if((count _resultPositions) > 0) then {
_firstResult = _resultPositions select 0;
_pos = _firstResult select 0;
_strongestResultPos = [_resultPositions, _povPos] call EFUNC(laser,findStrongestRay);
// If the laser has moved less than a half meter, then dont move it.
// Just regular use of lasers will commonly make them move this much,
// but not across multiple close frames.
// This loses accuracy a little, but saves position updates per frame.
TRACE_5("", diag_tickTime, _forceUpdateTime, getPosASL _laserTarget, _pos, ((getPosASL _laserTarget) distance _pos));
TRACE_5("", diag_tickTime, _forceUpdateTime, getPosASL _laserTarget, _strongestResultPos, ((getPosASL _laserTarget) distance _pos));
if(diag_tickTime > _forceUpdateTime) then {
TRACE_1("FCS Update", "");
["ace_fcs_forceUpdate", []] call ace_common_fnc_localEvent;
};
if( (_laserTarget distance _pos) > 0.1) then {
//if( (_laserTarget distance _strongestResultPos) > 0.1) then {
TRACE_1("LaserPos Update", "");
_laserTarget setPosATL (ASLToATL _pos);
};
_laserTarget setPosATL (ASLToATL _strongestResultPos);
//};
if(diag_tickTime > _forceUpdateTime) then {
_args set[2, diag_tickTime + FCS_UPDATE_DELAY];
@ -91,18 +88,19 @@ FUNC(laserHudDesignatePFH) = {
_this set[0, _args];
};
private "_laserTarget";
private "_handle";
private ["_laserTarget", "_handle", "_vehicle"];
if(isNil QGVAR(laser)) then {
_laserTarget = "LaserTargetW" createVehicle (getpos ACE_player);
_laserTarget = "LaserTargetW" createVehicle (getpos player);
GVAR(active) = true;
GVAR(laserActive) = true;
_handle = [FUNC(laserHudDesignatePFH), 0.1, [_laserTarget, player]] call cba_fnc_addPerFrameHandler;
_handle = [FUNC(laserHudDesignatePFH), 0.1, [_laserTarget, ACE_player]] call cba_fnc_addPerFrameHandler;
_laserTarget setVariable ["ACE_PFH_HANDLE", _handle, false];
// Clear the vehicle parameters
_vehicle setVariable[QGVAR(currentTarget), [], true];
GVAR(laser) = _laserTarget;
} else {
[] call FUNC(laserHudDesignateOff);

View File

@ -116,7 +116,7 @@ _startingTime = time;
// Swhich the unit back to its original group
[_unit, false, "ACE_isUnconscious", side group _unit] call EFUNC(common,switchToGroupSide);
[_unit, false] call EFUNC(common,disableAI_F);
[_unit, false] call EFUNC(common,disableAI);
_unit setUnitPos _originalPos; // This is not position but stance (DOWN, MIDDLE, UP)
_unit setUnconscious false;

View File

@ -0,0 +1,61 @@
class GVAR(AttackProfiles) {
class LIN {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_LIN);
};
class DIR {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_DIR);
};
class MID {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_MID);
};
class HI {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_HI);
};
class TOP {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_TOP);
};
class PYM {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_PYM);
};
};
class GVAR(SeekerTypes) {
class SALH {
name = "";
visualName = "";
description = "";
functionName = QFUNC(seekerType_SALH);
};
class Optic {
name = "";
visualName = "";
description = "";
functionName = QFUNC(seekerType_Optic);
};
};

View File

@ -0,0 +1,9 @@
class ACE_Settings {
class GVAR(enabled) {
value = 1;
typeName = "BOOL";
isClientSetable = 1;
displayName = "$STR_ACE_MissileGuidance";
description = "$STR_ACE_MissileGuidance_Desc";
};
};

View File

@ -1,10 +1,141 @@
enum {
ACE_LOBL = 1,
ACE_LOAL = 2
};
class CfgAmmo {
class MissileBase;
class M_PG_AT : MissileBase {
model = "\A3\Weapons_F\Ammo\Rocket_01_fly_F";
proxyShape = "\A3\Weapons_F\Ammo\Rocket_01_F";
irLock = 0;
laserLock = 0;
airLock = 0;
laserLock = 0;
airLock = 0;
weaponLockSystem = "2 + 16";
maxSpeed = 720;
maxControlRange = 5000;
maneuvrability = 8;
timeToLive = 60;
simulationStep = 0.01;
airFriction = 0.1;
sideAirFriction = 0.16;
initTime = 0.002;
thrustTime = 1.07;
thrust = 530;
fuseDistance = 2;
effectsMissileInit = "MissileDAR1";
effectsMissile = "missile2";
whistleDist = 4;
muzzleEffect = "";
// Turn off arma crosshair-guidance
manualControl = 0;
// ACE uses these values
trackOversteer = 1;
trackLead = 0;
// Begin ACE guidance Configs
class ACE_MissileGuidance {
enabled = 1;
minDeflection = 0.005; // Minium flap deflection for guidance
maxDeflection = 0.025; // Maximum flap deflection for guidance
incDeflection = 0.005; // The incrmeent in which deflection adjusts.
//minDeflection = 0.005;
//maxDeflection = 0.5;
//incDeflection = 0.005;
// Guidance type for munitions
defaultSeekerType = "SALH";
seekerTypes[] = { "SALH", "LIDAR", "SARH", "Optic", "Thermal", "GPS", "SACLOS", "MCLOS" };
defaultSeekerLockMode = "LOAL";
seekerLockModes[] = { "LOAL", "LOBL" };
seekerAngle = 90; // Angle in front of the missile which can be searched
seekerAccuracy = 1; // seeker accuracy multiplier
seekerMinRange = 1;
seekerMaxRange = 2500; // Range from the missile which the seeker can visually search
// Attack profile type selection
defaultAttackProfile = "LIN";
attackProfiles[] = { "LIN", "DIR", "MID", "HI", "TOP", "PYM" };
};
};
class ACE_Hydra70_DAGR : M_PG_AT {
displayName = "$STR_ACE_Hydra70_DAGR";
displayNameShort = "$STR_ACE_Hydra70_DAGR_Short";
description = "$STR_ACE_Hydra70_DAGR";
descriptionShort = "$STR_ACE_Hydra70_DAGR_Desc";
};
class ACE_Hellfire_AGM114K : ACE_Hydra70_DAGR {
displayName = "$STR_ACE_Hellfire_AGM114K";
displayNameShort = "$STR_ACE_Hellfire_AGM114K_Short";
description = "$STR_ACE_Hellfire_AGM114K_desc";
descriptionShort = "$STR_ACE_Hellfire_AGM114K_desc";
// @TODO: placeholder model to at least make it look different
model = "\A3\Weapons_F\Ammo\Missile_AT_03_fly_F";
proxyShape = "\A3\Weapons_F\Ammo\Missile_AT_03_F";
hit = 1400;
indirectHit = 71;
indirectHitRange = 4.5;
effectsMissile = "missile2";
};
// Titan
class M_Titan_AT : MissileBase {
irLock = 0;
laserLock = 0;
airLock = 0;
// Turn off arma crosshair-guidance
manualControl = 0;
hit = 1400;
// ACE uses these values
//trackOversteer = 1;
//trackLead = 0;
// Begin ACE guidance Configs
class ACE_MissileGuidance {
enabled = 1;
minDeflection = 0.005; // Minium flap deflection for guidance
maxDeflection = 0.25; // Maximum flap deflection for guidance
incDeflection = 0.005; // The incrmeent in which deflection adjusts.
//minDeflection = 0.005;
//maxDeflection = 0.5;
//incDeflection = 0.005;
// Guidance type for munitions
defaultSeekerType = "Optic";
seekerTypes[] = { "Optic" };
defaultSeekerLockMode = "LOBL";
seekerLockModes[] = { "LOBL" };
seekerAngle = 90; // Angle in front of the missile which can be searched
seekerAccuracy = 1; // seeker accuracy multiplier
seekerMinRange = 1;
seekerMaxRange = 2500; // Range from the missile which the seeker can visually search
// Attack profile type selection
defaultAttackProfile = "LIN";
attackProfiles[] = { "TOP", "LIN" };
};
};
};

View File

@ -5,13 +5,13 @@ class Extended_PreInit_EventHandlers {
};
class Extended_PostInit_EventHandlers {
class ADDON {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_post_init));
};
};
class Extended_FiredBIS_EventHandlers {
class AllVehicles {
class All {
ADDON = QUOTE(_this call FUNC(fired));
};
};

View File

@ -0,0 +1,53 @@
class CfgMagazines {
class 12Rnd_PG_missiles;
class 6Rnd_ACE_Hydra70_DAGR : 12Rnd_PG_missiles {
ammo = "ACE_Hydra70_DAGR";
count = 12;
displayName = "6 Round DAGR";
displayNameShort = "6 Round DAGR";
descriptionShort = "6 Round DAGR";
weight = 36;
};
class 12Rnd_ACE_Hydra70_DAGR : 6Rnd_ACE_Hydra70_DAGR {
count = 12;
displayName = "16 Round DAGR";
displayNameShort = "16 Round DAGR";
descriptionShort = "16 Round DAGR";
weight = 72;
};
class 24Rnd_ACE_Hydra70_DAGR : 6Rnd_ACE_Hydra70_DAGR {
count = 24;
displayName = "24 Round DAGR";
displayNameShort = "24 Round DAGR";
descriptionShort = "24 Round DAGR";
weight = 72;
};
// Hellfires
class 6Rnd_ACE_Hellfire_AGM114K : 12Rnd_PG_missiles {
count = 12;
ammo = "ACE_Hellfire_AGM114K";
displayName = "6Rnd_ACE_Hellfire_AGM114K";
displayNameShort = "6Rnd_ACE_Hellfire_AGM114K";
descriptionShort = "6Rnd_ACE_Hellfire_AGM114K";
weight = 36;
};
class 12Rnd_ACE_Hellfire_AGM114K : 6Rnd_ACE_Hydra70_DAGR {
count = 12;
displayName = "12Rnd_ACE_Hellfire_AGM114K";
displayNameShort = "12Rnd_ACE_Hellfire_AGM114K";
descriptionShort = "12Rnd_ACE_Hellfire_AGM114K";
weight = 72;
};
class 24Rnd_ACE_Hellfire_AGM114K : 6Rnd_ACE_Hydra70_DAGR {
count = 24;
displayName = "24Rnd_ACE_Hellfire_AGM114K";
displayNameShort = "24Rnd_ACE_Hellfire_AGM114K";
descriptionShort = "24Rnd_ACE_Hellfire_AGM114K";
weight = 72;
};
};

View File

@ -0,0 +1,24 @@
class CfgVehicles {
class Heli_Attack_01_base_F;
class B_Heli_Attack_01_F : Heli_Attack_01_base_F {
class Turrets {
class MainTurret;
};
}
class ACE_Comanche_Test : B_Heli_Attack_01_F {
displayName = "ACE_Comanche_Test";
author = "ACE Team";
class Library
{
libTextDesc = "ACE_Comanche_Test";
};
class Turrets: Turrets {
class MainTurret: MainTurret {
magazines[] = {"ACE_500Rnd_20mm_shells_Comanche", "24Rnd_ACE_Hellfire_AGM114K"};
};
};
};
};

View File

@ -6,29 +6,8 @@ class CfgWeapons {
class RocketPods: LauncherCore {
canLock = 1;
};
class missiles_DAGR: RocketPods {
class missiles_DAGR : RocketPods {
canLock = 1;
magazines[] += {"24Rnd_ACE_Hydra70_DAGR", "12Rnd_ACE_Hydra70_DAGR", "6Rnd_ACE_Hydra70_DAGR", "24Rnd_ACE_Hellfire_AGM114K", "12Rnd_ACE_Hellfire_AGM114K", "6Rnd_ACE_Hellfire_AGM114K" };
};
/*
class autocannon_Base_F: CannonCore {
canLock = 1;
};
class cannon_120mm: CannonCore {
canLock = 1;
class player : Mode_SemiAuto {
canLock = 1;
};
};
class gatling_25mm: CannonCore {
canLock = 1;
};
class autocannon_35mm: CannonCore {
canLock = 1;
};
class launch_NLAW_F: Launcher_Base_F
{
canLock = 1;
};*/
};

View File

@ -0,0 +1,65 @@
THIS IS A WIP FUNCTIONALITY, DUE TO CHANGE
class M_PG_AT : MissileBase {
model = "\A3\Weapons_F\Ammo\Rocket_01_fly_F";
proxyShape = "\A3\Weapons_F\Ammo\Rocket_01_F";
irLock = 0;
laserLock = 0;
airLock = 0;
weaponLockSystem = "2 + 16";
maxSpeed = 720;
maxControlRange = 5000;
maneuvrability = 8;
timeToLive = 60;
simulationStep = 0.01;
airFriction = 0.1;
sideAirFriction = 0.16;
initTime = 0.002;
thrustTime = 1.07;
thrust = 530;
fuseDistance = 2;
effectsMissileInit = "MissileDAR1";
effectsMissile = "missile2";
whistleDist = 4;
muzzleEffect = "";
// Turn off arma crosshair-guidance
manualControl = 0;
// ACE uses these values
trackOversteer = 1;
trackLead = 0;
// Begin ACE guidance Configs
class ACE_MissileGuidance {
enabled = 1;
minDeflection = 0.005; // Minium flap deflection for guidance
maxDeflection = 0.025; // Maximum flap deflection for guidance
incDeflection = 0.005; // The incrmeent in which deflection adjusts.
//minDeflection = 0.005;
//maxDeflection = 0.5;
//incDeflection = 0.005;
// Guidance type for munitions
defaultSeekerType = "SALH";
seekerTypes[] = { "SALH", "LIDAR", "SARH", "Optic", "Thermal", "GPS", "SACLOS", "MCLOS" };
defaultSeekerLockMode = "LOAL";
seekerLockModes[] = { "LOAL", "LOBL" };
seekerAngle = 90; // Angle in front of the missile which can be searched
seekerAccuracy = 1; // seeker accuracy multiplier
seekerMinRange = 1;
seekerMaxRange = 2500; // Range from the missile which the seeker can visually search
// Attack profile type selection
defaultAttackProfile = "LIN";
attackProfiles[] = { "LIN", "DIR", "MID", "HI", "TOP", "PYM" };
};
};

View File

@ -1,3 +1,2 @@
#include "script_component.hpp"
NO_DEDICATED;

View File

@ -3,12 +3,21 @@
PREP(rotateVectLineGetMap);
PREP(rotateVectLine);
PREP(translateToModelSpace);
PREP(translateToWeaponSpace);
PREP(fired);
PREP(guidance_DAGR);
PREP(guidance_LGB);
PREP(guidance_HellfireII);
FUNC(getPosASL) = {visiblePositionASL (_this select 0)};
PREP(guidancePFH);
PREP(doAttackProfile);
PREP(doSeekerSearch);
// Attack Profiles
PREP(attackProfile_LIN);
PREP(attackProfile_DIR);
PREP(attackProfile_MID);
PREP(attackProfile_HI);
PREP(attackProfile_TOP);
PREP(attackprofile_PYM);
PREP(attackProfile_AIR);
// Seeker search functions
PREP(seekerType_SALH);
PREP(seekerType_Optic);

View File

@ -10,6 +10,11 @@ class CfgPatches {
};
};
#include "ACE_GuidanceConfig.hpp"
#include "ACE_Settings.hpp"
#include "CfgEventhandlers.hpp"
#include "CfgAmmo.hpp"
#include "CfgWeapons.hpp"
#include "CfgMagazines.hpp"
#include "CfgWeapons.hpp"
#include "CfgVehicles.hpp"

View File

@ -0,0 +1,54 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos"];
_seekerTargetPos = _this select 0;
_launchParams = _this select 1;
_target = _launchParams select 0;
_targetLaunchParams = _launchParams select 1;
_shooterPos = getPosASL _shooter;
_projectilePos = getPosASL _projectile;
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
TRACE_2("", _distanceToTarget, _distanceToShooter);
// Add height depending on distance for compensate
_addHeight = [0,0,0];
// Always climb an arc on initial launch if we are close to the round
if( ((ASLtoATL _projectilePos) select 2) < 5 && _distanceToShooter < 15) then {
_addHeight = _addHeight vectorAdd [0,0,_distanceToTarget];
} else {
// If we are below the target, increase the climbing arc
if((_projectilePos select 2) < (_seekerTargetPos select 2) && _distanceToTarget > 100) then {
_addHeight = _addHeight vectorAdd [0,0, ((_seekerTargetPos select 2) - (_projectilePos select 2))];
};
};
// Handle arcing terminal low for high decent
if( (_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget < 100) then {
_addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2))];
} else {
if((_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget > 100) then {
_addHeight = _addHeight vectorAdd [0,0, _distanceToTarget];
};
};
TRACE_3("", _distanceToTarget,_distanceToShooter,_addHeight);
_returnTargetPos = _seekerTargetPos vectorAdd _addHeight;
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _returnTargetPos) vectorAdd _addHeight, ASLtoATL _returnTargetPos, [0,1,0,1]];
#endif
TRACE_1("Adjusted target position", _returnTargetPos);
_returnTargetPos;

View File

@ -0,0 +1,4 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
_this call FUNC(attackProfile_LIN);

View File

@ -0,0 +1,4 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
_this call FUNC(attackProfile_LIN);

View File

@ -0,0 +1,54 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos"];
_seekerTargetPos = _this select 0;
_launchParams = _this select 1;
_target = _launchParams select 0;
_targetLaunchParams = _launchParams select 1;
_shooterPos = getPosASL _shooter;
_projectilePos = getPosASL _projectile;
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
TRACE_2("", _distanceToTarget, _distanceToShooter);
// Add height depending on distance for compensate
_addHeight = [0,0,0];
// Always climb an arc on initial launch if we are close to the round
if( ((ASLtoATL _projectilePos) select 2) < 5 && _distanceToShooter < 15) then {
_addHeight = _addHeight vectorAdd [0,0,_distanceToTarget];
} else {
// If we are below the target, increase the climbing arc
if((_projectilePos select 2) < (_seekerTargetPos select 2) && _distanceToTarget > 100) then {
_addHeight = _addHeight vectorAdd [0,0, ((_seekerTargetPos select 2) - (_projectilePos select 2))];
};
};
// Handle arcing terminal low for high decent
if( (_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget < 100) then {
_addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.5];
} else {
if((_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget > 100) then {
_addHeight = _addHeight vectorAdd [0,0, _distanceToTarget*0.02];
};
};
TRACE_3("", _distanceToTarget,_distanceToShooter,_addHeight);
_returnTargetPos = _seekerTargetPos vectorAdd _addHeight;
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _returnTargetPos) vectorAdd _addHeight, ASLtoATL _returnTargetPos, [0,1,0,1]];
#endif
TRACE_1("Adjusted target position", _returnTargetPos);
_returnTargetPos;

View File

@ -0,0 +1,4 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
_this call FUNC(attackProfile_LIN);

View File

@ -0,0 +1,4 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
_this call FUNC(attackProfile_LIN);

View File

@ -0,0 +1,52 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos"];
_seekerTargetPos = _this select 0;
_launchParams = _this select 1;
_target = _launchParams select 0;
_targetLaunchParams = _launchParams select 1;
_shooterPos = getPosASL _shooter;
_projectilePos = getPosASL _projectile;
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
TRACE_2("", _distanceToTarget, _distanceToShooter);
// Add height depending on distance for compensate
_addHeight = [0,0,0];
// Always climb an arc on initial launch if we are close to the round
if( ((ASLtoATL _projectilePos) select 2) < 140 && _distanceToShooter < 50) then {
_addHeight = _addHeight vectorAdd [0,0,_distanceToTarget];
} else {
// If we are below the target, increase the climbing arc
if((_projectilePos select 2) < (_seekerTargetPos select 2) + 140 && _distanceToTarget > 100) then {
_addHeight = _addHeight vectorAdd [0,0, ((_seekerTargetPos select 2) - (_projectilePos select 2))+50];
};
};
// Handle arcing terminal low for high decent
if( (_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget < 140) then {
_addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.5];
} else {
if((_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget > 140) then {
_addHeight = _addHeight vectorAdd [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.02];
};
};
TRACE_3("", _distanceToTarget,_distanceToShooter,_addHeight);
_returnTargetPos = _seekerTargetPos vectorAdd _addHeight;
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _returnTargetPos) vectorAdd _addHeight, ASLtoATL _returnTargetPos, [0,1,0,1]];
#endif
TRACE_1("Adjusted target position", _returnTargetPos);
_returnTargetPos;

View File

@ -0,0 +1,30 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_attackProfilePos"];
_launchParams = ((_this select 1) select 1);
_attackProfileName = _launchParams select 3;
TRACE_1("Attacking profile", _attackProfileName);
_attackProfilesCfg = ( configFile >> QGVAR(AttackProfiles) );
_attackProfile = nil;
for [{_i=0}, {_i< (count _attackProfilesCfg) }, {_i=_i+1}] do {
_testProfile = _attackProfilesCfg select _i;
_testName = configName _testProfile;
TRACE_3("", _testName, _testProfile, _attackProfilesCfg);
if( _testName == _attackProfileName) exitWith {
_attackProfile = _attackProfilesCfg select _i;
};
};
_attackProfilePos = [0,0,0];
if(!isNil "_attackProfile") then {
_attackProfilePos = _this call (missionNamespace getVariable (getText (_attackProfile >> "functionName")));
};
_attackProfilePos;

View File

@ -0,0 +1,30 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_seekerProfilePos"];
_launchParams = ((_this select 1) select 1);
_seekerTypeName = _launchParams select 2;
TRACE_1("Seeker type", _seekerTypeName);
_seekerTypesCfg = ( configFile >> QGVAR(SeekerTypes) );
_seekerType = nil;
for [{_i=0}, {_i< (count _seekerTypesCfg) }, {_i=_i+1}] do {
_testProfile = _seekerTypesCfg select _i;
_testName = configName _testProfile;
TRACE_3("", _testName, _testProfile, _seekerTypesCfg);
if( _testName == _seekerTypeName) exitWith {
_seekerType = _seekerTypesCfg select _i;
};
};
_seekerProfilePos = [0,0,0];
if(!isNil "_seekerType") then {
_seekerProfilePos = _this call (missionNamespace getVariable (getText (_seekerType >> "functionName")));
};
_seekerProfilePos;

View File

@ -1,18 +1,80 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
//_this=[TEST_AI_HELICOPTER,"missiles_DAGR","missiles_DAGR","Far_AI","M_PG_AT","24Rnd_PG_missiles",163988: rocket_01_fly_f.p3d]
TRACE_1("enter", _this);
// Bail if guidance is disabled
if(!GVAR(enabled)) exitWith { false };
// Bail on locality of the projectile, it should be local to us
if(!local _projectile) exitWith { false };
private["_config", "_enabled", "_target", "_seekerType", "_attackProfile"];
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
if(!local _shooter) exitWith { false };
// Bail on not missile
if(! (_ammo isKindOf "MissileBase") ) exitWith { false };
switch _weapon do {
case "missiles_DAGR": {
_this call FUNC(guidance_DAGR);
};
case "GBU12BombLauncher": {
_this call FUNC(guidance_LGB);
_config = configFile >> "CfgAmmo" >> _ammo >> "ACE_MissileGuidance";
_enabled = getNumber ( _config >> "enabled");
// Bail if guidance is not enabled
if(isNil "_enabled" || {_enabled != 1}) exitWith { false };
_target = (vehicle _shooter) getVariable [QGVAR(target), nil];
_seekerType = (vehicle _shooter) getVariable [QGVAR(seekerType), nil];
_attackProfile = (vehicle _shooter) getVariable [QGVAR(attackProfile), nil];
_lockMode = (vehicle _shooter) getVariable [QGVAR(lockMode), nil];
TRACE_3("Begin guidance", _target, _seekerType, _attackProfile);
if ( isNil "_seekerType" || { ! ( _seekerType in (getArray (_config >> "seekerTypes" ) ) ) } ) then {
_seekerType = getText (_config >> "defaultSeekerType");
};
if ( isNil "_attackProfile" || { ! ( _attackProfile in (getArray (_config >> "attackProfiles" ) ) ) } ) then {
_attackProfile = getText (_config >> "defaultAttackProfile");
};
if ( isNil "_lockMode" || { ! ( _lockMode in (getArray (_config >> "seekerLockModes" ) ) ) } ) then {
_lockMode = getText (_config >> "defaultSeekerLockMode");
};
// If we didn't get a target, try to fall back on tab locking
if(isNil "_target") then {
_canUseLock = getNumber (_config >> "canVanillaLock");
if(_canUseLock > 0) then {
// @TODO: Get vanilla target
_vanillaTarget = cursorTarget;
TRACE_1("Using Vanilla Locking", _vanillaTarget);
if(!isNil "_vanillaTarget") then {
_target = _vanillaTarget;
};
};
};
//_this call FUNC(guidance_HellfireII);
TRACE_4("Beginning ACE guidance system",_target,_ammo,_seekerType,_attackProfile);
[FUNC(guidancePFH), 0, [_this,
[ACE_player,
[_target, _targetPos, _launchPos],
_seekerType,
_attackProfile,
_lockMode
],
[
getNumber ( _config >> "minDeflection" ),
getNumber ( _config >> "maxDeflection" ),
getNumber ( _config >> "incDeflection" )
],
[
getNumber ( _config >> "seekerAngle" ),
getNumber ( _config >> "seekerAccuracy" ),
getNumber ( _config >> "seekerMaxRange" )
],
[ diag_tickTime ]
]
] call cba_fnc_addPerFrameHandler;
/* Clears locking settings
(vehicle _shooter) setVariable [QGVAR(target), nil];
(vehicle _shooter) setVariable [QGVAR(seekerType), nil];
(vehicle _shooter) setVariable [QGVAR(attackProfile), nil];
(vehicle _shooter) setVariable [QGVAR(lockMode), nil];
*/

View File

@ -0,0 +1,97 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
#define TIMESTEP_FACTOR 0.01
private["_args", "_stateParams", "_launchParams", "_targetLaunchParams", "_config", "_flightParams", "_seekerParams", "_seekerTargetPos"];
private["_lastRunTime", "_runtimeDelta", "_profileAdjustedTargetPos", "_targetVectorSeeker", "_targetVector"];
private["_minDeflection", "_maxDeflection", "_incDeflection"];
private["_yVec", "_zVec", "_xVec"];
_args = _this select 0;
EXPLODE_7_PVT((_args select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_launchParams = _args select 1;
_targetLaunchParams = _launchParams select 1;
_flightParams = _args select 2;
_seekerParams = _args select 3;
_stateParams = _args select 4;
_lastRunTime = _stateParams select 0;
_runtimeDelta = diag_tickTime - _lastRunTime;
_config = configFile >> "CfgAmmo" >> _ammo >> "ACE_MissileGuidance";
if(!alive _projectile || isNull _projectile || isNull _shooter) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
// TODO: placeholder for "last seek target position"
_seekerTargetPos = [ [0,0,0], _args] call FUNC(doSeekerSearch);
if(!isNil "_seekerTargetPos") then {
_profileAdjustedTargetPos = [_seekerTargetPos,_args] call FUNC(doAttackProfile);
_minDeflection = _flightParams select 0;
_maxDeflection = _flightParams select 1;
_incDeflection = _flightParams select 2;
_yVec = vectorDir _projectile;
_zVec = vectorUp _projectile;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_projectilePos = getPosASL _projectile;
_targetVectorSeeker = [_projectile, [_xVec, _yVec, _zVec], _profileAdjustedTargetPos] call EFUNC(common,translateToWeaponSpace);
_targetVector = [0,0,0] vectorFromTo _targetVectorSeeker;
TRACE_1("", _targetVectorSeeker, _targetVector);
private["_yaw", "_pitch"];
_yaw = 0;
_pitch = 0;
if((_targetVectorSeeker select 0) < 0) then {
_yaw = - ( (_minDeflection max (abs(_targetVector select 0) min _maxDeflection) ) );
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = ( (_minDeflection max ((_targetVector select 0) min _maxDeflection) ) );
};
};
if((_targetVectorSeeker select 2) < 0) then {
_pitch = - ( (_minDeflection max (abs(_targetVector select 2) min _maxDeflection) ) );
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = ( (_minDeflection max ((_targetVector select 2) min _maxDeflection) ) );
};
};
#ifdef DEBUG_MODE_FULL
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _projectilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _projectilePos, ASLtoATL _profileAdjustedTargetPos, [1,0,0,1]];
#endif
if(accTime > 0) then {
private["_adjustTime", "_outVector", "_vectorTo"];
_adjustTime = 1/accTime;
_adjustTime = _adjustTime * (_runtimeDelta / TIMESTEP_FACTOR);
TRACE_4("Adjust timing", 1/accTime, _adjustTime, _runtimeDelta, (_runtimeDelta / TIMESTEP_FACTOR) );
// @TODO: Apply velocity multiplier to yaw/pitch. Basically, it can adjust faster at lower speeds
//_adjustDeflection = (vectorMagnitude velocity _projectile);
_outVector = [_projectile, [_xVec, _yVec, _zVec], [_yaw, _adjustTime, _pitch]] call EFUNC(common,translateToModelSpace);
_vectorTo = _projectilePos vectorFromTo _outVector;
_projectile setVectorDirAndUp [_vectorTo, vectorUp _projectile];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _distanceToTarget];
#endif
};
_stateParams set[0, diag_tickTime];
_args set[4, _stateParams];
_this set[0, _args];

View File

@ -1,120 +0,0 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
FUNC(guidance_DIRECT_LOAL_PFH) = {
//TRACE_1("enter", _this);
private["_args", "_shooter", "_dagr", "_curVelocity", "_targets", "_target", "_yVec", "_xVec", "_zVec", "_dagrPos", "_shooterPos", "_distanceToTarget", "_distanceToShooter", "_def"];
_args = _this select 0;
//PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_shooter = _args select 0;
_dagr = _args select 6;
_curVelocity = velocity _dagr;
if(!alive _dagr || isNull _dagr || isNull _shooter) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_targets = [_dagr, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call ace_laser_fnc_findLaserDesignator;
TRACE_2("Targets", _target, _targets);
if((_targets select 0)) then {
_target = _targets select 1;
// player sideChat "FUCK!";
// drop ["\a3\data_f\Cl_basic","","Billboard",1,20,(getPos _dagr),[0,0,0],1,1.275,1.0,0.0,[5],[[1,0,0,1]],[0],0.0,2.0,"","",""];
_yVec = vectorDir _dagr;
_zVec = vectorUp _dagr;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_dagrPos = getPosASL _dagr;
// player sideChat "G!";
_targetPos = getPosASL _target;
_shooterPos = getPosASL _shooter;
if((count _targetPos) > 0) then {
_distanceToTarget = _dagrPos vectorDistance _targetPos;
_distanceToShooter = _dagrPos vectorDistance _shooterPos;
_addHeight = [0,0,(_dagrPos distance _targetPos)*0.02];
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]];
#endif
_targetPos = _targetPos vectorAdd _addHeight;
_def = 0.0040;
if(_distanceToShooter > 100) then {
_def = 0.0025;
};
_targetVectorSeeker = [_dagr, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace);
// _targetVectorSeeker = _dagr worldToModel (ASLtoATL _targetPos);
// _targetVectorSeeker = [0,0,0] vectorFromTo _targetVectorSeeker;
_yaw = 0.0;
if((_targetVectorSeeker select 0) < 0) then {
_yaw = -_def;
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = _def;
};
};
_pitch = 0.0;
if((_targetVectorSeeker select 2) < 0) then {
_pitch = -_def;
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = _def;
};
};
#ifdef DEBUG_MODE_FULL
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _dagrPos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _dagrPos, ASLtoATL _targetPos, [1,0,0,1]];
_distance = ([getPos startPos, _dagrPos] call BIS_fnc_distance2D);
_marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _dagrPos select 2]];
_marker setMarkerTypeLocal "mil_dot";
_marker setMarkerColorLocal "ColorRed";
MARKERCOUNT = MARKERCOUNT + 1;
#endif
if(accTime > 0) then {
_outVector = [_dagr, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace);
// _outVector = _dagr modelToWorldVisual [_yaw, 1, _pitch];
// _outVector = ATLtoASL _outVector;
_vectorTo = _dagrPos vectorFromTo _outVector;
// hintSilent format["v: %1", _vectorTo];
// _dagr setVectorDir _vectorTo;
_dagr setVectorDirAndUp [_vectorTo, vectorUp _dagr];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _distanceToTarget];
#endif
};
};
};
FUNC(guidance_DAGR_DIRECT_LOAL) = {
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
GVAR(lastTime) = time;
[FUNC(guidance_DIRECT_LOAL_PFH), 0, _this] call cba_fnc_addPerFrameHandler;
};
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION];
switch (_fireMode select 0) do {
// Default to FIREMODE_DIRECT_LOAL
// FIREMODE_DIRECT_LOAL
default {
LOG("Initiating DAGR FIREMODE_DIRECT_LOAL");
_this call FUNC(guidance_DAGR_DIRECT_LOAL);
};
};

View File

@ -1,249 +0,0 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
FUNC(guidance_Hellfire_LOAL_HI_PFH) = {
//TRACE_1("enter", _this);
_args = _this select 0;
//PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_shooter = _args select 0;
_missile = _args select 6;
_curVelocity = velocity _missile;
if(!alive _missile || isNull _missile || isNull _shooter) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_launchPos = _shooter getVariable [QGVAR(launchPos), nil];
if(isNil "_launchPos") then {
TRACE_1("Setting launch parameters", "");
_launchPos = getPosASL _shooter;
_shooter setVariable [QGVAR(launchPos), _launchPos, false];
_shooter setVariable [QGVAR(launchTime), diag_tickTime, false];
};
_targets = [_missile, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call ace_laser_fnc_findLaserDesignator;
_addHeight = [0,0,0];
if((_targets select 0)) then {
_target = _targets select 1;
TRACE_2("Targets", _target, _targets);
_yVec = vectorDir _missile;
_zVec = vectorUp _missile;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_missilePos = getPosASL _missile;
// player sideChat "G!";
_targetPos = getPosASL _target;
TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos));
if((count _targetPos) > 0) then {
_distanceToTarget = _missilePos vectorDistance _targetPos;
_defPitch = 0.05;
if((_launchPos distance _missilePos) < 400 && (_targetPos distance _missilePos) > 400) then {
_addHeight = [0,0,(_targetPos select 2) + ((_launchPos distance _targetPos)*2)];
TRACE_1("Climb phase", _addHeight);
//_defPitch = 0.1;
} else {
// Covered half the distance, go terminal
if((_missilePos distance _targetPos) < (_launchPos distance _targetPos) / 2) then {
TRACE_1("TERMINAL", "");
} else {
if((_missilePos select 2) > (_targetPos select 2)) then {
_heightDiff = (_missilePos select 2) - (_targetPos select 2);
TRACE_1("Coasting", _heightDiff);
_addHeight = [0,0, _heightDiff];
};
};
};
_targetPos = _targetPos vectorAdd _addHeight;
_defYaw = 0.0035;
_targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace);
_yaw = 0.0;
if((_targetVectorSeeker select 0) < 0) then {
_yaw = -_defYaw;
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = _defYaw;
};
};
_pitch = 0.0;
if((_targetVectorSeeker select 2) < 0) then {
_pitch = -_defPitch;
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = _defPitch;
};
};
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]];
_light = "#lightpoint" createVehicleLocal (getPos _missile);
_light setLightBrightness 1.0;
_light setLightAmbient [1.0, 0.0, 0.0];
_light setLightColor [1.0, 0.0, 0.0];
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]];
_distance = ([getPos startPos, _missilePos] call BIS_fnc_distance2D);
_marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _missilePos select 2]];
_marker setMarkerTypeLocal "mil_dot";
_marker setMarkerColorLocal "ColorRed";
MARKERCOUNT = MARKERCOUNT + 1;
#endif
if(accTime > 0) then {
_outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace);
_vectorTo = _missilePos vectorFromTo _outVector;
_missile setVectorDirAndUp [_vectorTo, vectorUp _missile];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _distanceToTarget];
#endif
};
};
};
FUNC(guidance_Hellfire_LOAL_DIR_PFH) = {
//TRACE_1("enter", _this);
_args = _this select 0;
//PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_shooter = _args select 0;
_missile = _args select 6;
_curVelocity = velocity _missile;
if(!alive _missile || isNull _missile || isNull _shooter) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_launchPos = _shooter getVariable [QGVAR(launchPos), nil];
if(isNil "_launchPos") then {
TRACE_1("Setting launch parameters", "");
_launchPos = getPosASL _shooter;
_shooter setVariable [QGVAR(launchPos), _launchPos, false];
_shooter setVariable [QGVAR(launchTime), diag_tickTime, false];
};
_targets = [_missile, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call ace__laser_fnc_findLaserDesignator;
_addHeight = [0,0,0];
if((_targets select 0)) then {
_target = _targets select 1;
TRACE_2("Targets", _target, _targets);
_yVec = vectorDir _missile;
_zVec = vectorUp _missile;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_missilePos = getPosASL _missile;
// player sideChat "G!";
_targetPos = getPosASL _target;
TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos));
if((count _targetPos) > 0) then {
_distanceToTarget = _missilePos vectorDistance _targetPos;
if((_launchPos distance _missilePos) < 400 && (_targetPos distance _missilePos) > 400) then {
_addHeight = [0,0,(_targetPos select 2) + (_missilePos distance _targetPos)*0.5];
TRACE_1("Climb phase", _addHeight);
} else {
// Covered half the distance, go terminal
if((_missilePos distance _targetPos) < (_launchPos distance _targetPos) / 2) then {
TRACE_1("TERMINAL", "");
} else {
if((_missilePos select 2) > (_targetPos select 2)) then {
_heightDiff = (_missilePos select 2) - (_targetPos select 2);
TRACE_1("Coasting", _heightDiff);
_addHeight = [0,0, _heightDiff];
};
};
};
_targetPos = _targetPos vectorAdd _addHeight;
_defYaw = 0.0035;
_defPitch = 0.0075;
_targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace);
_yaw = 0.0;
if((_targetVectorSeeker select 0) < 0) then {
_yaw = -_defYaw;
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = _defYaw;
};
};
_pitch = 0.0;
if((_targetVectorSeeker select 2) < 0) then {
_pitch = -_defPitch;
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = _defPitch;
};
};
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]];
_light = "#lightpoint" createVehicleLocal (getPos _missile);
_light setLightBrightness 1.0;
_light setLightAmbient [1.0, 0.0, 0.0];
_light setLightColor [1.0, 0.0, 0.0];
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]];
_distance = ([getPos startPos, _missilePos] call BIS_fnc_distance2D);
_marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _missilePos select 2]];
_marker setMarkerTypeLocal "mil_dot";
_marker setMarkerColorLocal "ColorRed";
MARKERCOUNT = MARKERCOUNT + 1;
#endif
if(accTime > 0) then {
_outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace);
_vectorTo = _missilePos vectorFromTo _outVector;
_missile setVectorDirAndUp [_vectorTo, vectorUp _missile];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _distanceToTarget];
#endif
};
};
};
FUNC(guidance_Hellfire_LOAL_HI) = {
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
GVAR(lastTime) = time;
[FUNC(guidance_Hellfire_LOAL_HI_PFH), 0, _this] call cba_fnc_addPerFrameHandler;
};
FUNC(guidance_Hellfire_LOAL_DIR) = {
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
GVAR(lastTime) = time;
[FUNC(guidance_Hellfire_LOAL_DIR_PFH), 0, _this] call cba_fnc_addPerFrameHandler;
};
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION];
switch (_fireMode select 0) do {
// Default to FIREMODE_DIRECT_LOAL
// FIREMODE_DIRECT_LOAL
default {
LOG("Initiating Hellfire II FIREMODE_LOAL_DIR");
_this call FUNC(guidance_Hellfire_LOAL_HI);
};
};

View File

@ -1,109 +0,0 @@
#define DEBUG_MODE_FULL
#include "script_component.hpp"
FUNC(guidance_LGB_LOAL_PFH) = {
//TRACE_1("enter", _this);
_args = _this select 0;
//PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_lgb = _args select 6;
_curVelocity = velocity _lgb;
if(!alive _lgb) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_targets = [_lgb, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call uo_laser_fnc_findLaserDesignator;
//TRACE_2("Targets", _target, _targets);
if((_targets select 0)) then {
_target = _targets select 1;
// player sideChat "FUCK!";
// drop ["\a3\data_f\Cl_basic","","Billboard",1,20,(getPos _lgb),[0,0,0],1,1.275,1.0,0.0,[5],[[1,0,0,1]],[0],0.0,2.0,"","",""];
_yVec = vectorDir _lgb;
_zVec = vectorUp _lgb;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_lgbPos = getPosASL _lgb;
// player sideChat "G!";
_targetPos = getPosASL _target;
if((count _targetPos) > 0) then {
// player sideChat format["f: %1", _targetPos];
_addHeight = [0,0,(_lgbPos distance _targetPos)*0.06];
// drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]];
_targetPos = _targetPos vectorAdd _addHeight;
_def = 0.0025;
_targetVectorSeeker = [_lgb, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace);
// _targetVectorSeeker = _lgb worldToModel (ASLtoATL _targetPos);
// _targetVectorSeeker = [0,0,0] vectorFromTo _targetVectorSeeker;
_yaw = 0.0;
if((_targetVectorSeeker select 0) < 0) then {
_yaw = -_def;
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = _def;
};
};
_pitch = 0.0;
if((_targetVectorSeeker select 2) < 0) then {
_pitch = -_def;
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = _def;
};
};
#ifdef DEBUG_MODE_FULL
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _lgbPos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _lgbPos, ASLtoATL _targetPos, [1,0,0,1]];
_distance = ([getPos startPos, _lgbPos] call BIS_fnc_distance2D);
_marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _lgbPos select 2]];
_marker setMarkerTypeLocal "mil_dot";
_marker setMarkerColorLocal "ColorRed";
MARKERCOUNT = MARKERCOUNT + 1;
#endif
if(accTime > 0) then {
_outVector = [_lgb, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace);
// _outVector = _lgb modelToWorldVisual [_yaw, 1, _pitch];
// _outVector = ATLtoASL _outVector;
_vectorTo = _lgbPos vectorFromTo _outVector;
// hintSilent format["v: %1", _vectorTo];
// _lgb setVectorDir _vectorTo;
_lgb setVectorDirAndUp [_vectorTo, vectorUp _lgb];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _lgbPos vectorDistance _targetPos];
#endif
};
};
};
FUNC(guidance_LGB_LOAL) = {
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
[FUNC(guidance_LGB_LOAL_PFH), 0, _this] call cba_fnc_addPerFrameHandler;
};
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION];
switch (_fireMode select 0) do {
// Default to FIREMODE_DIRECT_LOAL
// FIREMODE_DIRECT_LOAL
default {
LOG("Initiating FIREMODE_DIRECT_LOAL");
_this call FUNC(guidance_LGB_LOAL);
};
};

View File

@ -0,0 +1,32 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_targets", "_foundTargetPos", "_launchParams", "_seekerParams", "_targetLaunchParams"];
_seekerTargetPos = _this select 0;
_launchParams = _this select 1;
_target = (((_launchParams select 1) select 1) select 0);
_seekerParams = _launchParams select 3;
TRACE_1("", _this);
TRACE_1("", _launchParams);
// TODO:: Make sure the missile maintains LOS
_foundTargetPos = [0,0,0];
if(!isNil "_target") then {
_foundTargetPos = getPosASL _target;
};
TRACE_2("", _target, _foundTargetPos);
_projectileSpeed = (vectorMagnitude velocity _projectile);
_distanceToTarget = (getPosASL _projectile) vectorDistance _foundTargetPos;
_eta = _distanceToTarget / _projectileSpeed;
_adjustVelocity = (velocity _target) vectorMultiply _eta;
_foundTargetPos = _foundTargetPos vectorAdd _adjustVelocity;
_foundTargetPos;

View File

@ -0,0 +1,17 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
private["_targets", "_foundTargetPos", "_launchParams", "_seekerParams", "_targetLaunchParams"];
_seekerTargetPos = _this select 0;
_launchParams = _this select 1;
_seekerParams = _launchParams select 3;
// TODO: this needs to be shootCone/findStrongestRay after testing
_targets = [_projectile, ACE_DEFAULT_LASER_CODE, (_seekerParams select 0)] call ace_laser_fnc_findLaserDesignator;
_foundTargetPos = getPosASL (_targets select 1);
TRACE_1("Seeker return target pos", _foundTargetPos);
_foundTargetPos;

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Edited with tabler - 2014-12-22 -->
<Project name="ACE">
<Package name="missileguidance">
<Key ID="STR_ACE_MissileGuidance">
<English>Advanced Missile Guidance</English>
<Spanish>Avanzada Misiles Orientación</Spanish>
<French>Avancée Missile orientation</French>
<Polish>Asystent Missile</Polish>
<German>Erweiterte Missile Guidance</German>
<Czech>Advanced Missile Guidance</Czech>
<Italian>Avanzato Missile Guidance</Italian>
<Portuguese>Avançado Missile Guidance</Portuguese>
<Hungarian>Részletes rakéta irányító</Hungarian>
<Russian>Расширенный ракетой</Russian>
</Key>
<Key ID="STR_ACE_MissileGuidance_Desc">
<English>Enables advanced guidance mechanics and selection for different missiles and fire modes.</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
/* Weapons */
<Key ID="STR_ACE_Hydra70_DAGR">
<English>Hydra-70 DAGR Missile</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
<Key ID="STR_ACE_Hydra70_DAGR_Short">
<English>DAGR</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
<Key ID="STR_ACE_Hydra70_DAGR_Desc">
<English>Hydra-70 DAGR Laser Guided Missile</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
/* Weapons */
<Key ID="STR_ACE_Hellfire_AGM114K">
<English>Hellfire II AGM-114K Missile</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
<Key ID="STR_ACE_Hellfire_AGM114K_Short">
<English>AGM-114K</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
<Key ID="STR_ACE_Hellfire_AGM114K_desc">
<English>Hellfire II AGM-114K Laser Guided Missile</English>
<Spanish></Spanish>
<French></French>
<Polish></Polish>
<German></German>
<Czech></Czech>
<Italian></Italian>
<Portuguese></Portuguese>
<Hungarian></Hungarian>
<Russian></Russian>
</Key>
</Package>
</Project>

View File

@ -230,6 +230,7 @@ class CfgWeapons {
class Snip: Snip {
modelOptics[] = {QUOTE(PATHTOF(models\ace_optics_pip.p3d)),QUOTE(PATHTOF(models\ace_optics_pip.p3d))};
};
class Iron: Iron {};
};
};
};

View File

@ -9,10 +9,4 @@ class Extended_PostInit_EventHandlers {
init = QUOTE(call COMPILE_FILE(XEH_post_init));
clientInit = QUOTE(call COMPILE_FILE(XEH_clientInit));
};
};
class Extended_FiredBIS_EventHandlers {
class CAManBase {
ADDON = QUOTE(_this call FUNC(fired));
};
};

View File

@ -1,13 +1,13 @@
#include "script_component.hpp"
PREP(fired);
PREP(translateToWeaponSpace);
PREP(translateToModelSpace);
PREP(lockKeyDown);
PREP(lockKeyUp);
PREP(cycleFireMode);
PREP(showFireMode);
PREP(onOpticLoad);
PREP(onOpticDraw);

View File

@ -5,7 +5,7 @@ class CfgPatches {
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_laser"};
requiredAddons[] = { "ace_main", "ace_common", "ace_missileguidance" };
VERSION_CONFIG;
};
};

View File

@ -1,19 +1,13 @@
#define DEBUG_MODE_FULL
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
TRACE_1("enter", _this);
private["_player", "_currentFireMode"];
_currentFireMode = ACE_player getVariable["ACE_FIRE_SELECTION", ACE_JAV_FIREMODE_TOP];
if(_currentFireMode == ACE_JAV_FIREMODE_DIR) then {
_currentFireMode = ACE_JAV_FIREMODE_TOP;
__JavelinIGUITop ctrlSetTextColor __ColorGreen;
__JavelinIGUIDir ctrlSetTextColor __ColorGray;
_currentFireMode = ACE_player getVariable["ace_missileguidance_attackProfile", "TOP"];
if(_currentFireMode == "LIN") then {
_currentFireMode = "TOP";
} else {
_currentFireMode = ACE_JAV_FIREMODE_DIR;
__JavelinIGUITop ctrlSetTextColor __ColorGray;
__JavelinIGUIDir ctrlSetTextColor __ColorGreen;
_currentFireMode = "LIN";
};
ACE_player setVariable["ACE_FIRE_SELECTION", _currentFireMode, false];
ACE_player setVariable["ace_missileguidance_attackProfile", _currentFireMode, false];

View File

@ -1,285 +0,0 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
//_this=[TEST_AI_HELICOPTER,"missiles_DAGR","missiles_DAGR","Far_AI","M_PG_AT","24Rnd_PG_missiles",163988: rocket_01_fly_f.p3d]
TRACE_1("Launch", _this);
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
FUNC(guidance_Javelin_LOBL_DIR_PFH) = {
TRACE_1("enter", _this);
private["_pitch", "_yaw", "_wentTerminal", "_target", "_targetPos", "_curVelocity", "_missile",
"_launchPos", "_targetStartPos", "_defPitch", "_defYaw"];
_args = _this select 0;
//PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_shooter = _args select 0;
_missile = _args select 6;
if((count _args) > 7) then {
_saveArgs = _args select 7;
_target = _saveArgs select 0;
_targetStartPos = _saveArgs select 1;
_launchPos = _saveArgs select 2;
_wentTerminal = _saveArgs select 3;
} else {
_wentTerminal = false;
_launchPos = getPosASL _shooter;
_target = ACE_player getVariable[QGVAR(currentTarget), objNull];
_targetStartPos = ACE_player getVariable[QGVAR(currentTargetPos), [0,0,0]];
};
if(!alive _missile || isNull _missile || isNull _target) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_targetPos = getPosASL _target;
_curVelocity = velocity _missile;
TRACE_4("", _target, _targetPos, _launchPos, _targetStartPos);
_addHeight = [0,0,0];
if(!isNil "_target") then {
_yVec = vectorDir _missile;
_zVec = vectorUp _missile;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_missilePos = getPosASL _missile;
// player sideChat "G!";
TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos));
if((count _targetPos) > 0) then {
_distanceToTarget = [(_missilePos select 0), (_missilePos select 1), (_targetPos select 2)] vectorDistance _targetPos;
if( (_missilePos select 2) < (_targetPos select 2) + 60 && !_wentTerminal) then {
_addHeight = [0,0,(_targetPos select 2) + 120];
_defPitch = 0.15;
_defYaw = 0.035;
TRACE_1("Climb phase", _addHeight);
} else {
_wentTerminal = true;
_this set[2, _wentTerminal];
_defPitch = 0.15;
_defYaw = 0.035;
TRACE_1("TERMINAL", "");
};
_targetPos = _targetPos vectorAdd _addHeight;
_targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace);
TRACE_5("", _missile, _xVec, _yVec, _zVec, _targetPos);
_yaw = 0.0;
_pitch = 0.0;
if((_targetVectorSeeker select 0) < 0) then {
_yaw = -_defYaw;
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = _defYaw;
};
};
if((_targetVectorSeeker select 2) < 0) then {
_pitch = -_defPitch;
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = _defPitch;
};
};
TRACE_3("", _targetVectorSeeker, _pitch, _yaw);
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]];
_light = "#lightpoint" createVehicleLocal (getPos _missile);
_light setLightBrightness 1.0;
_light setLightAmbient [1.0, 0.0, 0.0];
_light setLightColor [1.0, 0.0, 0.0];
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]];
MARKERCOUNT = MARKERCOUNT + 1;
#endif
if(accTime > 0) then {
TRACE_5("", _xVec, _yVec, _zVec, _yaw, _pitch);
_outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace);
_vectorTo = _missilePos vectorFromTo _outVector;
TRACE_3("", _missile, _outVector, _vectorTo);
_missile setVectorDirAndUp [_vectorTo, vectorUp _missile];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _distanceToTarget];
#endif
};
};
_saveArgs = [_target,_targetStartPos, _launchPos, _wentTerminal];
_args set[7, _saveArgs ];
_this set[0, _args];
};
FUNC(guidance_Javelin_LOBL_TOP_PFH) = {
TRACE_1("enter", _this);
private["_pitch", "_yaw", "_wentTerminal", "_target", "_targetPos", "_curVelocity", "_missile",
"_launchPos", "_targetStartPos", "_defPitch", "_defYaw"];
_args = _this select 0;
//PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
_shooter = _args select 0;
_missile = _args select 6;
if((count _args) > 7) then {
_saveArgs = _args select 7;
_target = _saveArgs select 0;
_targetStartPos = _saveArgs select 1;
_launchPos = _saveArgs select 2;
_wentTerminal = _saveArgs select 3;
} else {
_wentTerminal = false;
_launchPos = getPosASL _shooter;
_target = ACE_player getVariable[QGVAR(currentTarget), objNull];
_targetStartPos = ACE_player getVariable[QGVAR(currentTargetPos), [0,0,0]];
};
if(!alive _missile || isNull _missile || isNull _target) exitWith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_targetPos = getPosASL _target;
_curVelocity = velocity _missile;
TRACE_4("", _target, _targetPos, _launchPos, _targetStartPos);
_addHeight = [0,0,0];
if(!isNil "_target") then {
_yVec = vectorDir _missile;
_zVec = vectorUp _missile;
_xVec = vectorNormalized (_yVec vectorCrossProduct _zVec);
_missilePos = getPosASL _missile;
// player sideChat "G!";
TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos));
if((count _targetPos) > 0) then {
_distanceToTarget = [(_missilePos select 0), (_missilePos select 1), (_targetPos select 2)] vectorDistance _targetPos;
if( (_missilePos select 2) < (_targetPos select 2) + 200 && !_wentTerminal) then {
_addHeight = [0,0, ( (_distanceToTarget * 2) + 400)];
_defPitch = 0.25;
_defYaw = 0.035;
TRACE_1("Climb phase", _addHeight);
} else {
_wentTerminal = true;
_this set[2, _wentTerminal];
_defPitch = 0.25;
_defYaw = 0.25;
TRACE_1("TERMINAL", "");
};
_targetPos = _targetPos vectorAdd _addHeight;
_targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace);
TRACE_5("", _missile, _xVec, _yVec, _zVec, _targetPos);
_yaw = 0.0;
_pitch = 0.0;
// Stop jinking on terminal final decent
if((_missilePos distance _targetPos) < 150) then {
_defPitch = 0.0015;
_defYaw = 0.0015;
};
if((_targetVectorSeeker select 0) < 0) then {
_yaw = -_defYaw;
} else {
if((_targetVectorSeeker select 0) > 0) then {
_yaw = _defYaw;
};
};
if((_targetVectorSeeker select 2) < 0) then {
_pitch = -_defPitch;
} else {
if((_targetVectorSeeker select 2) > 0) then {
_pitch = _defPitch;
};
};
TRACE_3("", _targetVectorSeeker, _pitch, _yaw);
#ifdef DEBUG_MODE_FULL
drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]];
_light = "#lightpoint" createVehicleLocal (getPos _missile);
_light setLightBrightness 1.0;
_light setLightAmbient [1.0, 0.0, 0.0];
_light setLightColor [1.0, 0.0, 0.0];
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]];
MARKERCOUNT = MARKERCOUNT + 1;
#endif
if(accTime > 0) then {
TRACE_5("", _xVec, _yVec, _zVec, _yaw, _pitch);
_outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace);
_vectorTo = _missilePos vectorFromTo _outVector;
TRACE_3("", _missile, _outVector, _vectorTo);
_missile setVectorDirAndUp [_vectorTo, vectorUp _missile];
};
#ifdef DEBUG_MODE_FULL
hintSilent format["d: %1", _distanceToTarget];
#endif
};
};
_saveArgs = [_target,_targetStartPos, _launchPos, _wentTerminal];
_args set[7, _saveArgs ];
_this set[0, _args];
};
FUNC(guidance_Javelin_LOBL_TOP) = {
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
GVAR(lastTime) = time;
[FUNC(guidance_Javelin_LOBL_TOP_PFH), 0, _this] call cba_fnc_addPerFrameHandler;
};
FUNC(guidance_Javelin_LOBL_DIR) = {
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
GVAR(lastTime) = time;
[FUNC(guidance_Javelin_LOBL_DIR_PFH), 0, _this] call cba_fnc_addPerFrameHandler;
};
if(!local _shooter) exitWith { false };
if(_ammo == "M_Titan_AT") then {
_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_JAV_FIREMODE_TOP];
switch (_fireMode) do {
// Default to FIREMODE_DIRECT_LOAL
// FIREMODE_DIRECT_LOAL
case ACE_JAV_FIREMODE_DIR: {
LOG("Initiating Javelin FIREMODE_LOBL_DIR");
_this call FUNC(guidance_Javelin_LOBL_DIR);
};
default {
LOG("Initiating Javelin FIREMODE_LOBL_TOP");
_this call FUNC(guidance_Javelin_LOBL_TOP);
};
};
};

View File

@ -1,3 +1,3 @@
#define DEBUG_MODE_FULL
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
TRACE_1("enter", _this);

View File

@ -1,3 +1,3 @@
#define DEBUG_MODE_FULL
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
TRACE_1("enter", _this);

View File

@ -7,15 +7,6 @@
#define __LOCKONTIMERANDOM 0.3 // Deviation in lock on time
#define __SENSORSQUARE 1 // Locking on sensor square side in angles
#define __ConstraintTop (((ctrlPosition __JavelinIGUITargetingConstrainTop) select 1) + ((ctrlPosition (__JavelinIGUITargetingConstrainTop)) select 3))
#define __ConstraintBottom ((ctrlPosition __JavelinIGUITargetingConstrainBottom) select 1)
#define __ConstraintLeft (((ctrlPosition __JavelinIGUITargetingConstrainLeft) select 0) + ((ctrlPosition (__JavelinIGUITargetingConstrainLeft)) select 2))
#define __ConstraintRight ((ctrlPosition __JavelinIGUITargetingConstrainRight) select 0)
#define __OffsetX ((ctrlPosition __JavelinIGUITargetingLineV) select 0) - 0.5
#define __OffsetY ((ctrlPosition __JavelinIGUITargetingLineH) select 1) - 0.5
private["_args", "_lastTick", "_runTime", "_soundTime", "_lockTime", "_newTarget", "_currentTarget", "_range", "_pos", "_targetArray"];
// Reset arguments if we havnt rendered in over a second
@ -41,6 +32,9 @@ if ((velocity ACE_player) distance [0,0,0] > 0.5 && {cameraView == "GUNNER"} &&
ACE_player switchCamera "INTERNAL";
};
// Refresh the firemode
[] call FUNC(showFireMode);
// Only start locking on holding tab
if(!GVAR(isLockKeyDown)) exitWith { false };
@ -68,7 +62,7 @@ if (isNull _newTarget) then {
__JavelinIGUITargetingGate ctrlShow false;
__JavelinIGUITargetingLines ctrlShow false;
ACE_player setVariable [QGVAR(currentTarget),nil, false];
ACE_player setVariable ["ace_missileguidance_target",nil, false];
// Disallow fire
//if (ACE_player ammo "Javelin" > 0 || {ACE_player ammo "ACE_Javelin_Direct" > 0}) then {ACE_player setWeaponReloadingTime //[player, "Javelin", 0.2];};
@ -91,8 +85,7 @@ if (isNull _newTarget) then {
__JavelinIGUINFOV ctrlSetTextColor __ColorNull;
__JavelinIGUITargetingConstrains ctrlShow true;
ACE_player setVariable[QGVAR(currentTarget), _currentTarget, false];
ACE_player setVariable[QGVAR(currentTargetPos), getPosASL _currentTarget, false];
ACE_player setVariable["ace_missileguidance_target", _currentTarget, false];
if(diag_tickTime > _soundTime) then {
playSound "ACE_Javelin_Locked";
@ -115,7 +108,7 @@ if (isNull _newTarget) then {
__JavelinIGUITargetingGate ctrlShow false;
__JavelinIGUITargetingLines ctrlShow false;
ACE_player setVariable [QGVAR(currentTarget),nil, false];
ACE_player setVariable ["ace_missileguidance_target",nil, false];
};
};

View File

@ -6,6 +6,11 @@ if((count _this) > 0) then {
uiNameSpace setVariable ['ACE_RscOptics_javelin',_this select 0];
};
ACE_player setVariable ["ace_missileguidance_target",nil, false];
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
__JavelinIGUINFOV ctrlSetTextColor __ColorGray;
uiNameSpace setVariable [QGVAR(arguments),
[
0, // Last runtime

View File

@ -0,0 +1,14 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
TRACE_1("enter", _this);
private["_player", "_currentFireMode"];
_currentFireMode = ACE_player getVariable["ace_missileguidance_attackProfile", "TOP"];
if(_currentFireMode == "TOP") then {
__JavelinIGUITop ctrlSetTextColor __ColorGreen;
__JavelinIGUIDir ctrlSetTextColor __ColorGray;
} else {
__JavelinIGUITop ctrlSetTextColor __ColorGray;
__JavelinIGUIDir ctrlSetTextColor __ColorGreen;
};

View File

@ -46,6 +46,15 @@
#define __JavelinIGUITargetingLineH (__JavelinIGUI displayCtrl 699301)
#define __JavelinIGUITargetingLineV (__JavelinIGUI displayCtrl 699302)
#define __ConstraintTop (((ctrlPosition __JavelinIGUITargetingConstrainTop) select 1) + ((ctrlPosition (__JavelinIGUITargetingConstrainTop)) select 3))
#define __ConstraintBottom ((ctrlPosition __JavelinIGUITargetingConstrainBottom) select 1)
#define __ConstraintLeft (((ctrlPosition __JavelinIGUITargetingConstrainLeft) select 0) + ((ctrlPosition (__JavelinIGUITargetingConstrainLeft)) select 2))
#define __ConstraintRight ((ctrlPosition __JavelinIGUITargetingConstrainRight) select 0)
#define __OffsetX ((ctrlPosition __JavelinIGUITargetingLineV) select 0) - 0.5
#define __OffsetY ((ctrlPosition __JavelinIGUITargetingLineH) select 1) - 0.5
// Colors for controls
#define __ColorOrange [0.9255,0.5216,0.1216,1]
#define __ColorGreen [0.2941,0.8745,0.2157,1]

828
tools/make64.py Normal file
View File

@ -0,0 +1,828 @@
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# make.py
# An Arma 3 addon build system
###############################################################################
# The MIT License (MIT)
# Copyright (c) 2013-2014 Ryan Schultz
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
###############################################################################
__version__ = "0.3dev"
import sys
if sys.version_info[0] == 2:
print("Python 3 is required.")
sys.exit(1)
import os
import os.path
import shutil
import platform
import glob
import subprocess
import hashlib
import configparser
import json
import traceback
import time
import re
if sys.platform == "win32":
import winreg
###############################################################################
# http://akiscode.com/articles/sha-1directoryhash.shtml
# Copyright (c) 2009 Stephen Akiki
# MIT License (Means you can do whatever you want with this)
# See http://www.opensource.org/licenses/mit-license.php
# Error Codes:
# -1 -> Directory does not exist
# -2 -> General error (see stack traceback)
def get_directory_hash(directory):
directory_hash = hashlib.sha1()
if not os.path.exists (directory):
return -1
try:
for root, dirs, files in os.walk(directory):
for names in files:
path = os.path.join(root, names)
try:
f = open(path, 'rb')
except:
# You can't open the file for some reason
f.close()
continue
while 1:
# Read file in as little chunks
buf = f.read(4096)
if not buf: break
new = hashlib.sha1(buf)
directory_hash.update(new.digest())
f.close()
except:
# Print the stack traceback
traceback.print_exc()
return -2
return directory_hash.hexdigest()
# Copyright (c) André Burgaud
# http://www.burgaud.com/bring-colors-to-the-windows-console-with-python/
if sys.platform == "win32":
from ctypes import windll, Structure, c_short, c_ushort, byref
SHORT = c_short
WORD = c_ushort
class COORD(Structure):
"""struct in wincon.h."""
_fields_ = [
("X", SHORT),
("Y", SHORT)]
class SMALL_RECT(Structure):
"""struct in wincon.h."""
_fields_ = [
("Left", SHORT),
("Top", SHORT),
("Right", SHORT),
("Bottom", SHORT)]
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
"""struct in wincon.h."""
_fields_ = [
("dwSize", COORD),
("dwCursorPosition", COORD),
("wAttributes", WORD),
("srWindow", SMALL_RECT),
("dwMaximumWindowSize", COORD)]
# winbase.h
STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12
# wincon.h
FOREGROUND_BLACK = 0x0000
FOREGROUND_BLUE = 0x0001
FOREGROUND_GREEN = 0x0002
FOREGROUND_CYAN = 0x0003
FOREGROUND_RED = 0x0004
FOREGROUND_MAGENTA = 0x0005
FOREGROUND_YELLOW = 0x0006
FOREGROUND_GREY = 0x0007
FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
BACKGROUND_BLACK = 0x0000
BACKGROUND_BLUE = 0x0010
BACKGROUND_GREEN = 0x0020
BACKGROUND_CYAN = 0x0030
BACKGROUND_RED = 0x0040
BACKGROUND_MAGENTA = 0x0050
BACKGROUND_YELLOW = 0x0060
BACKGROUND_GREY = 0x0070
BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
def get_text_attr():
"""Returns the character attributes (colors) of the console screen
buffer."""
csbi = CONSOLE_SCREEN_BUFFER_INFO()
GetConsoleScreenBufferInfo(stdout_handle, byref(csbi))
return csbi.wAttributes
def set_text_attr(color):
"""Sets the character attributes (colors) of the console screen
buffer. Color is a combination of foreground and background color,
foreground and background intensity."""
SetConsoleTextAttribute(stdout_handle, color)
###############################################################################
def find_bi_tools(work_drive):
"""Find BI tools."""
reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER)
try:
k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools")
arma3tools_path = winreg.QueryValueEx(k, "path")[0]
winreg.CloseKey(k)
except:
raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.")
addonbuilder_path = os.path.join(arma3tools_path, "AddonBuilder", "AddonBuilder.exe")
dssignfile_path = os.path.join(arma3tools_path, "DSSignFile", "DSSignFile.exe")
dscreatekey_path = os.path.join(arma3tools_path, "DSSignFile", "DSCreateKey.exe")
cfgconvert_path = os.path.join(arma3tools_path, "CfgConvert", "CfgConvert.exe")
if os.path.isfile(addonbuilder_path) and os.path.isfile(dssignfile_path) and os.path.isfile(dscreatekey_path) and os.path.isfile(cfgconvert_path):
return [addonbuilder_path, dssignfile_path, dscreatekey_path, cfgconvert_path]
else:
raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.")
def find_depbo_tools(regKey):
"""Use registry entries to find DePBO-based tools."""
stop = False
if regKey == "HKCU":
reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER)
stop = True
else:
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
try:
k = winreg.OpenKey(reg, r"Software\Wow6432Node\Mikero\pboProject")
try:
pboproject_path = winreg.QueryValueEx(k, "exe")[0]
winreg.CloseKey(k)
print("Found pboproject.")
except:
print_error("ERROR: Could not find pboProject.")
k = winreg.OpenKey(reg, r"Software\Wow6432Node\Mikero\rapify")
try:
rapify_path = winreg.QueryValueEx(k, "exe")[0]
winreg.CloseKey(k)
print("Found rapify.")
except:
print_error("Could not find rapify.")
k = winreg.OpenKey(reg, r"Software\Wow6432Node\Mikero\MakePbo")
try:
makepbo_path = winreg.QueryValueEx(k, "exe")[0]
winreg.CloseKey(k)
print("Found makepbo.")
except:
print_error("Could not find makepbo.")
except:
if stop == True:
raise Exception("BadDePBO", "DePBO tools not installed correctly")
return -1
#Strip any quotations from the path due to a MikeRo tool bug which leaves a trailing space in some of its registry paths.
return [pboproject_path.strip('"'),rapify_path.strip('"'),makepbo_path.strip('"')]
def color(color):
"""Set the color. Works on Win32 and normal terminals."""
if sys.platform == "win32":
if color == "green":
set_text_attr(FOREGROUND_GREEN | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "red":
set_text_attr(FOREGROUND_RED | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "blue":
set_text_attr(FOREGROUND_BLUE | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "reset":
set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070)
elif color == "grey":
set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070)
else :
if color == "green":
sys.stdout.write('\033[92m')
elif color == "red":
sys.stdout.write('\033[91m')
elif color == "blue":
sys.stdout.write('\033[94m')
elif color == "reset":
sys.stdout.write('\033[0m')
def print_error(msg):
color("red")
print ("ERROR: " + msg)
color("reset")
def print_green(msg):
color("green")
print(msg)
color("reset")
def print_blue(msg):
color("blue")
print(msg)
color("reset")
def print_yellow(msg):
color("yellow")
print(msg)
color("reset")
###############################################################################
def main(argv):
"""Build an Arma addon suite in a directory from rules in a make.cfg file."""
print_blue(("\nmake.py for Arma, v" + __version__))
if sys.platform != "win32":
print_error("Non-Windows platform (Cygwin?). Please re-run from cmd.")
sys.exit(1)
reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER)
try:
k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools")
arma3tools_path = winreg.QueryValueEx(k, "path")[0]
winreg.CloseKey(k)
except:
raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.")
# Default behaviors
test = False # Copy to Arma 3 directory?
arg_modules = False # Only build modules on command line?
make_release = False # Make zip file from the release?
release_version = 0 # Version of release
use_pboproject = True # Default to pboProject build tool
make_target = "DEFAULT" # Which section in make.cfg to use for the build
new_key = False # Make a new key and use it to sign?
quiet = False # Suppress output from build tool?
# Parse arguments
if "help" in argv or "-h" in argv or "--help" in argv:
print ("""
make.py [help] [test] [force] [key <name>] [target <name>] [release <version>]
[module name] [module name] [...]
test -- Copy result to Arma 3.
release <version> -- Make archive with <version>.
force -- Ignore cache and build all.
target <name> -- Use rules in make.cfg under heading [<name>] rather than
default [Make]
key <name> -- Use key in working directory with <name> to sign. If it does not
exist, create key.
quiet -- Suppress command line output from build tool.
If module names are specified, only those modules will be built.
Examples:
make.py force test
Build all modules (ignoring cache) and copy the mod folder to the Arma 3
directory.
make.py mymodule_gun
Only build the module named 'mymodule_gun'.
make.py force key MyNewKey release 1.0
Build all modules (ignoring cache), sign them with NewKey, and pack them
into a zip file for release with version 1.0.
If a file called $NOBIN$ is found in the module directory, that module will not be binarized.
See the make.cfg file for additional build options.
""")
sys.exit(0)
if "force" in argv:
argv.remove("force")
force_build = True
else:
force_build = False
if "test" in argv:
test = True
argv.remove("test")
if "release" in argv:
make_release = True
release_version = argv[argv.index("release") + 1]
argv.remove(release_version)
argv.remove("release")
if "target" in argv:
make_target = argv[argv.index("target") + 1]
argv.remove("target")
argv.remove(make_target)
force_build = True
if "key" in argv:
new_key = True
key_name = argv[argv.index("key") + 1]
argv.remove("key")
argv.remove(key_name)
if "quiet" in argv:
quiet = True
argv.remove("quiet")
# Get the directory the make script is in.
make_root = os.path.dirname(os.path.realpath(__file__))
make_root_parent = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
os.chdir(make_root)
# Get latest commit ID
try:
gitpath = os.path.join(os.path.dirname(make_root), ".git")
assert os.path.exists(gitpath)
commit_id = subprocess.check_output(["git", "rev-parse", "HEAD"])
commit_id = str(commit_id, "utf-8")[:8]
except:
print_error("FAILED TO DETERMINE COMMIT ID.")
commit_id = "NOGIT"
cfg = configparser.ConfigParser();
try:
cfg.read(os.path.join(make_root, "make.cfg"))
# Project name (with @ symbol)
project = cfg.get(make_target, "project", fallback="@"+os.path.basename(os.getcwd()))
# Private key path
key = cfg.get(make_target, "key", fallback=None)
# Project prefix (folder path)
prefix = cfg.get(make_target, "prefix", fallback="")
# Should we autodetect modules on a complete build?
module_autodetect = cfg.getboolean(make_target, "module_autodetect", fallback=True)
# Manual list of modules to build for a complete build
modules = cfg.get(make_target, "modules", fallback=None)
# Parse it out
if modules:
modules = [x.strip() for x in modules.split(',')]
else:
modules = []
# List of directories to ignore when detecting
ignore = [x.strip() for x in cfg.get(make_target, "ignore", fallback="release").split(',')]
# BI Tools work drive on Windows
work_drive = cfg.get(make_target, "work_drive", fallback="P:\\")
# Which build tool should we use?
build_tool = cfg.get(make_target, "build_tool", fallback="addonbuilder").lower()
# Release/build directory, relative to script dir
release_dir = cfg.get(make_target, "release_dir", fallback="release")
# Project PBO file prefix (files are renamed to prefix_name.pbo)
pbo_name_prefix = cfg.get(make_target, "pbo_name_prefix", fallback=None)
# Project module Root
module_root_parent = os.path.abspath(os.path.join(os.path.join(work_drive, prefix), os.pardir))
module_root = cfg.get(make_target, "module_root", fallback=os.path.join(make_root_parent, "addons"))
print_green ("module_root: " + module_root)
if (os.path.isdir(module_root)):
os.chdir(module_root)
else:
print_error ("Directory " + module_root + " does not exist.")
sys.exit()
except:
raise
print_error("Could not parse make.cfg.")
sys.exit(1)
# See if we have been given specific modules to build from command line.
if len(argv) > 1 and not make_release:
arg_modules = True
modules = argv[1:]
# Find the tools we need.
try:
tools = find_bi_tools(work_drive)
addonbuilder = tools[0]
dssignfile = tools[1]
dscreatekey = tools[2]
cfgconvert = tools[3]
except:
print_error("Arma 3 Tools are not installed correctly or the P: drive has not been created.")
sys.exit(1)
if build_tool == "pboproject":
try:
depbo_tools = find_depbo_tools("HKLM")
if depbo_tools == -1:
depbo_tools = find_depbo_tools("HKCU")
pboproject = depbo_tools[0]
rapifyTool = depbo_tools[1]
makepboTool = depbo_tools[2]
except:
raise
print_error("Could not find dePBO tools. Download the needed tools from: https://dev.withsix.com/projects/mikero-pbodll/files")
sys.exit(1)
# Try to open and deserialize build cache file.
try:
cache = {}
with open(os.path.join(make_root, "make.cache"), 'r') as f:
cache_raw = f.read()
cache = json.loads(cache_raw)
except:
print ("No cache found.")
cache = {}
# Get list of subdirs in make root.
dirs = next(os.walk(module_root))[1]
# Autodetect what directories to build.
if module_autodetect and not arg_modules:
modules = []
for path in dirs:
# Any dir that has a config.cpp in its root is an addon to build.
config_path = os.path.join(path, 'config.cpp')
if os.path.isfile(config_path) and not path in ignore:
modules.append(path)
# Make the key specified from command line if necessary.
if new_key:
if not os.path.isfile(os.path.join(module_root, key_name + ".biprivatekey")):
print_green("\nRequested key does not exist.")
ret = subprocess.call([dscreatekey, key_name]) # Created in make_root
if ret == 0:
print_blue("Created: " + os.path.join(module_root, key_name + ".biprivatekey"))
else:
print_error("Failed to create key!")
try:
print_blue("Copying public key to release directory.")
try:
os.makedirs(os.path.join(module_root, release_dir, "Keys"))
except:
pass
shutil.copyfile(os.path.join(module_root, key_name + ".bikey"), os.path.join(module_root, release_dir, "Keys", key_name + ".bikey"))
except:
raise
print_error("Could not copy key to release directory.")
else:
print_green("\nNOTE: Using key " + os.path.join(module_root, key_name + ".biprivatekey"))
key = os.path.join(module_root, key_name + ".biprivatekey")
# For each module, prep files and then build.
for module in modules:
print_green("\nMaking " + module + "-"*max(1, (60-len(module))))
# Cache check
if module in cache:
old_sha = cache[module]
else:
old_sha = ""
# Hash the module
new_sha = get_directory_hash(os.path.join(module_root, module))
# Check if it needs rebuilt
# print ("Hash:", new_sha)
if old_sha == new_sha:
if not force_build:
print("Module has not changed.")
# Skip everything else
continue
# Only do this if the project isn't stored directly on the work drive.
# Split the path at the drive name and see if they are on the same drive (usually P:)
if os.path.splitdrive(module_root)[0] != os.path.splitdrive(work_drive)[0]:
try:
# Remove old work drive version (ignore errors)
shutil.rmtree(os.path.join(work_drive, prefix, module), True)
# Copy module to the work drive
shutil.copytree(module, os.path.join(work_drive, prefix, module))
except:
raise
print_error("ERROR: Could not copy module to work drive. Does the module exist?")
input("Press Enter to continue...")
print("Resuming build...")
continue
#else:
#print("WARNING: Module is stored on work drive (" + work_drive + ").")
try:
# Remove the old pbo, key, and log
old = os.path.join(module_root, release_dir, project, "Addons", module) + "*"
files = glob.glob(old)
for f in files:
os.remove(f)
if pbo_name_prefix:
old = os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix+module) + "*"
files = glob.glob(old)
for f in files:
os.remove(f)
except:
raise
print_error("ERROR: Could not copy module to work drive. Does the module exist?")
input("Press Enter to continue...")
print("Resuming build...")
continue
# Build the module into a pbo
print_blue("Building: " + os.path.join(work_drive, prefix, module))
print_blue("Destination: " + os.path.join(module_root, release_dir, project, "Addons"))
# Make destination folder (if needed)
try:
os.makedirs(os.path.join(module_root, release_dir, project, "Addons"))
except:
pass
# Run build tool
build_successful = False
if build_tool == "pboproject":
try:
#PABST: Convert config (run the macro'd config.cpp through CfgConvert twice to produce a de-macro'd cpp that pboProject can read without fucking up:
shutil.copyfile(os.path.join(work_drive, prefix, module, "config.cpp"), os.path.join(work_drive, prefix, module, "config.backup"))
os.chdir("P:\\")
cmd = [os.path.join(arma3tools_path, "CfgConvert", "CfgConvert.exe"), "-bin", "-dst", os.path.join(work_drive, prefix, module, "config.bin"), os.path.join(work_drive, prefix, module, "config.cpp")]
ret = subprocess.call(cmd)
if ret != 0:
print_error("CfgConvert -bin return code == " + str(ret))
input("Press Enter to continue...")
cmd = [os.path.join(arma3tools_path, "CfgConvert", "CfgConvert.exe"), "-txt", "-dst", os.path.join(work_drive, prefix, module, "config.cpp"), os.path.join(work_drive, prefix, module, "config.bin")]
ret = subprocess.call(cmd)
if ret != 0:
print_error("CfgConvert -txt) return code == " + str(ret))
input("Press Enter to continue...")
# Include build number
try:
configpath = os.path.join(work_drive, prefix, module, "config.cpp")
f = open(configpath, "r")
configtext = f.read()
f.close()
patchestext = re.search(r"class CfgPatches\n\{(.*?)\n\}", configtext, re.DOTALL).group(1)
patchestext = re.sub(r'version(.*?)="(.*?)"', r'version\1="\2-{}"'.format(commit_id), patchestext)
configtext = re.sub(r"class CfgPatches\n\{(.*?)\n\}", "class CfgPatches\n{"+patchestext+"\n}", configtext, flags=re.DOTALL)
f = open(configpath, "w")
f.write(configtext)
f.close()
except:
raise
print_error("Failed to include build number")
continue
if os.path.isfile(os.path.join(work_drive, prefix, module, "$NOBIN$")):
print_green("$NOBIN$ Found. Proceeding with non-binarizing!")
cmd = [makepboTool, "-P","-A","-L","-N","-G", os.path.join(work_drive, prefix, module),os.path.join(module_root, release_dir, project,"Addons")]
else:
cmd = [pboproject, "-P", os.path.join(work_drive, prefix, module), "+Engine=Arma3", "-S","+Noisy", "+X", "+Clean", "+Mod="+os.path.join(module_root, release_dir, project), "-Key"]
color("grey")
if quiet:
devnull = open(os.devnull, 'w')
ret = subprocess.call(cmd, stdout=devnull)
devnull.close()
else:
ret = subprocess.call(cmd)
color("reset")
if ret == 0:
print_green("pboProject return code == " + str(ret))
# Prettyprefix rename the PBO if requested.
if pbo_name_prefix:
try:
os.rename(os.path.join(module_root, release_dir, project, "Addons", module+".pbo"), os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix+module+".pbo"))
except:
raise
print_error("Could not rename built PBO with prefix.")
# Sign result
if key:
print("Signing with " + key + ".")
if pbo_name_prefix:
ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix + module + ".pbo")])
else:
ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "Addons", module + ".pbo")])
if ret == 0:
build_successful = True
else:
build_successful = True
if not build_successful:
print_error("pboProject return code == " + str(ret))
print_error("Module not successfully built/signed.")
input("Press Enter to continue...")
print ("Resuming build...")
continue
#PABST: cleanup config BS (you could comment this out to see the "de-macroed" cpp
#print_green("\Pabst (restoring): " + os.path.join(work_drive, prefix, module, "config.cpp"))
os.remove(os.path.join(work_drive, prefix, module, "config.cpp"))
os.remove(os.path.join(work_drive, prefix, module, "config.bin"))
os.rename(os.path.join(work_drive, prefix, module, "config.backup"), os.path.join(work_drive, prefix, module, "config.cpp"))
# Back to the root
os.chdir(module_root)
except:
raise
print_error("Could not run Addon Builder.")
input("Press Enter to continue...")
print ("Resuming build...")
continue
elif build_tool== "addonbuilder":
# Detect $NOBIN$ and do not binarize if found.
if os.path.isfile(os.path.join(work_drive, prefix, module, "$NOBIN$")):
do_binarize = False
print("$NOBIN$ file found in module, packing only.")
else:
do_binarize = True
try:
# Call AddonBuilder
os.chdir("P:\\")
cmd = [addonbuilder, os.path.join(work_drive, prefix, module), os.path.join(make_root, release_dir, project, "Addons"), "-clear", "-project="+work_drive]
if not do_binarize:
cmd.append("-packonly")
if quiet:
previousDirectory = os.getcwd()
os.chdir(arma3tools_path)
devnull = open(os.devnull, 'w')
ret = subprocess.call(cmd, stdout=devnull)
devnull.close()
os.chdir(previousDirectory)
else:
previousDirectory = os.getcwd()
os.chdir(arma3tools_path)
print_error("Current directory - " + os.getcwd())
ret = subprocess.call(cmd)
os.chdir(previousDirectory)
print_error("Current directory - " + os.getcwd())
color("reset")
print_green("completed")
# Prettyprefix rename the PBO if requested.
if pbo_name_prefix:
try:
os.rename(os.path.join(make_root, release_dir, project, "Addons", module+".pbo"), os.path.join(make_root, release_dir, project, "Addons", pbo_name_prefix+module+".pbo"))
except:
raise
print_error("Could not rename built PBO with prefix.")
if ret == 0:
# Sign result
if key:
print("Signing with " + key + ".")
if pbo_name_prefix:
ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "Addons", pbo_name_prefix + module + ".pbo")])
else:
ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "Addons", module + ".pbo")])
if ret == 0:
build_successful = True
else:
build_successful = True
if not build_successful:
print_error("Module not successfully built.")
# Back to the root
os.chdir(make_root)
except:
raise
print_error("Could not run Addon Builder.")
input("Press Enter to continue...")
print ("Resuming build...")
continue
else:
print_error("Unknown build_tool " + build_tool + "!")
# Update the hash for a successfully built module
if build_successful:
cache[module] = new_sha
# Done building all modules!
# Write out the cache state
cache_out = json.dumps(cache)
with open(os.path.join(make_root, "make.cache"), 'w') as f:
f.write(cache_out)
# Delete the pboproject temp files if building a release.
if make_release and build_tool == "pboproject":
try:
shutil.rmtree(os.path.join(module_root, release_dir, project, "temp"), True)
except:
print_error("ERROR: Could not delete pboProject temp files.")
print_green("\nDone.")
# Make release
if make_release:
print_blue("\nMaking release: " + project + "-" + release_version + ".zip")
try:
# Delete all log files
for root, dirs, files in os.walk(os.path.join(module_root, release_dir, project, "Addons")):
for currentFile in files:
if currentFile.lower().endswith("log"):
os.remove(os.path.join(root, currentFile))
# Create a zip with the contents of release/ in it
shutil.make_archive(project + "-" + release_version, "zip", os.path.join(module_root, release_dir))
except:
raise
print_error("Could not make release.")
# Copy to Arma 3 folder for testing
if test:
print_blue("\nCopying to Arma 3.")
if sys.platform == "win32":
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
try:
k = winreg.OpenKey(reg, r"SOFTWARE\Wow6432Node\Bohemia Interactive\Arma 3")
a3_path = winreg.EnumValue(k, 1)[1]
winreg.CloseKey(k)
except:
print_error("Could not find Arma 3's directory in the registry.")
else:
a3_path = cygwin_a3path
if os.path.exists(a3_path):
try:
shutil.rmtree(os.path.join(a3_path, project), True)
shutil.copytree(os.path.join(module_root, release_dir, project), os.path.join(a3_path, project))
except:
print_error("Could not copy files. Is Arma 3 running?")
if __name__ == "__main__":
main(sys.argv)
input("Press Enter to continue...")