mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Merge branch 'master' of https://github.com/acemod/ACE3 into medical-rewrite
This commit is contained in:
commit
0f43829b63
@ -15,6 +15,12 @@ if (!alive ACE_player) exitWith { // Dead people don't breath, Will also handle
|
||||
|
||||
private _currentWork = REE;
|
||||
private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6;
|
||||
|
||||
// fix #4481. Diving to the ground is recorded as PRONE stance with running speed velocity. Cap maximum speed to fix.
|
||||
if (stance ACE_player == "PRONE") then {
|
||||
_currentSpeed = _currentSpeed min 1.5;
|
||||
};
|
||||
|
||||
if ((vehicle ACE_player == ACE_player) && {_currentSpeed > 0.1} && {isTouchingGround ACE_player || {underwater ACE_player}}) then {
|
||||
_currentWork = [ACE_player, _currentSpeed] call FUNC(getMetabolicCosts);
|
||||
_currentWork = _currentWork max REE;
|
||||
|
@ -38,5 +38,5 @@ if (_pov == "pip0_pos") then {
|
||||
|
||||
_povDir = _gunBeginPos vectorDiff _gunEndPos;
|
||||
};
|
||||
|
||||
_povDir = vectorNormalized _povDir;
|
||||
[_povPos, _povDir]
|
||||
|
@ -6,4 +6,16 @@ class ACE_Settings {
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
};
|
||||
class GVAR(enableAmmobox) {
|
||||
displayName = CSTRING(enableBoxCookoff_name);
|
||||
description = CSTRING(enableBoxCookoff_tooltip);
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
};
|
||||
class GVAR(enableAmmoCookoff) {
|
||||
displayName = CSTRING(enableAmmoCookoff_name);
|
||||
description = CSTRING(enableAmmoCookoff_tooltip);
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
};
|
||||
};
|
||||
|
33
addons/cookoff/CfgAmmo.hpp
Normal file
33
addons/cookoff/CfgAmmo.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
class CfgAmmo {
|
||||
class ShellBase;
|
||||
class ace_ammoExplosion: ShellBase {
|
||||
hit = 10;
|
||||
indirectHit = 0.5;
|
||||
indirectHitRange = 1;
|
||||
soundHit[] = {"", 1, 1, 0};
|
||||
typicalSpeed = 100;
|
||||
explosive = 0;
|
||||
cost = 300;
|
||||
model = "\A3\Weapons_F\empty.p3d";
|
||||
airFriction = 0;
|
||||
timeToLive = 1;
|
||||
explosionTime = 0.001;
|
||||
soundFly[] = {"",1,1};
|
||||
soundEngine[] = {"",1,4};
|
||||
explosionEffects = "ExploAmmoExplosion";
|
||||
};
|
||||
|
||||
class SmallSecondary;
|
||||
class ACE_ammoExplosionLarge: SmallSecondary {
|
||||
soundHit[] = {"", 1, 1, 0};
|
||||
model = "\A3\Weapons_F\empty.p3d";
|
||||
soundFly[] = {"",1,1};
|
||||
soundEngine[] = {"",1,4};
|
||||
soundHit1[] = {"",1,1,1};
|
||||
soundHit2[] = {"",1,1,1};
|
||||
soundHit3[] = {"",1,1,1};
|
||||
supersonicCrackFar[] = {"",1,1,1};
|
||||
supersonicCrackNear[] = {"",1,1,1};
|
||||
craterEffects = "ImpactEffectsMedium";
|
||||
};
|
||||
};
|
@ -52,3 +52,30 @@ class CfgCloudlets {
|
||||
destroyOnWaterSurfaceOffset = 0;
|
||||
};
|
||||
};
|
||||
|
||||
class GVAR(ExploAmmoExplosion) {
|
||||
class ExploAmmoFlash {
|
||||
position[] = {0,0,0};
|
||||
simulation = "particles";
|
||||
type = "ExploAmmoFlash";
|
||||
intensity = 1;
|
||||
interval = 1;
|
||||
lifeTime = 1;
|
||||
};
|
||||
class LightExplosion {
|
||||
simulation = "light";
|
||||
type = "SparksLight";
|
||||
position[] = {0,0,0};
|
||||
intensity = 1;
|
||||
interval = 1;
|
||||
lifeTime = 0.15;
|
||||
};
|
||||
class ExploAmmoSmoke {
|
||||
position[] = {0,0,0};
|
||||
simulation = "particles";
|
||||
type = "AutoCannonFired";
|
||||
intensity = 1.5;
|
||||
interval = 1.5;
|
||||
lifeTime = 1.5;
|
||||
};
|
||||
};
|
||||
|
@ -2,5 +2,7 @@
|
||||
PREP(handleDamage);
|
||||
PREP(engineFire);
|
||||
PREP(cookOff);
|
||||
PREP(cookOffBox);
|
||||
PREP(blowOffTurret);
|
||||
PREP(secondaryExplosions);
|
||||
PREP(detonateAmmunition);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
[QGVAR(engineFire), FUNC(engineFire)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOff), FUNC(cookOff)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOffBox), FUNC(cookOffBox)] call CBA_fnc_addEventHandler;
|
||||
|
||||
GVAR(cacheTankDuplicates) = call CBA_fnc_createNamespace;
|
||||
|
||||
@ -52,21 +53,31 @@ GVAR(cacheTankDuplicates) = call CBA_fnc_createNamespace;
|
||||
}];
|
||||
}, nil, ["Wheeled_APC_F"], true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
["ReammoBox_F", "init", {
|
||||
(_this select 0) addEventHandler ["HandleDamage", {
|
||||
if (GVAR(enableAmmobox)) then {
|
||||
["box", _this] call FUNC(handleDamage);
|
||||
};
|
||||
}];
|
||||
}, nil, nil, true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
// secondary explosions
|
||||
["AllVehicles", "killed", {
|
||||
params ["_vehicle"];
|
||||
|
||||
if (_vehicle getVariable [QGVAR(enable), GVAR(enable)]) then {
|
||||
if (_vehicle getVariable [QGVAR(enable),GVAR(enable)]) then {
|
||||
_vehicle call FUNC(secondaryExplosions);
|
||||
if (_vehicle getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmoCookoff)]) then {
|
||||
[_vehicle, magazinesAmmo _vehicle] call FUNC(detonateAmmunition);
|
||||
};
|
||||
};
|
||||
}, nil, ["Man"]] call CBA_fnc_addClassEventHandler;
|
||||
}, nil, ["Man","StaticWeapon"]] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
// blow off turret effect
|
||||
["Tank", "killed", {
|
||||
params ["_vehicle"];
|
||||
|
||||
if (_vehicle getVariable [QGVAR(enable), GVAR(enable)]) then {
|
||||
_vehicle call FUNC(blowOffTurret);
|
||||
if ((_this select 0) getVariable [QGVAR(enable),GVAR(enable)]) then {
|
||||
if (random 1 < 0.15) then {
|
||||
(_this select 0) call FUNC(blowOffTurret);
|
||||
};
|
||||
};
|
||||
}] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
|
@ -8,7 +8,7 @@ class CfgPatches {
|
||||
requiredVersion = REQUIRED_VERSION;
|
||||
requiredAddons[] = {"ace_common"};
|
||||
author = ECSTRING(common,ACETeam);
|
||||
authors[] = {"commy2"};
|
||||
authors[] = {"commy2", "Glowbal"};
|
||||
url = ECSTRING(main,URL);
|
||||
VERSION_CONFIG;
|
||||
};
|
||||
@ -18,6 +18,7 @@ class CfgPatches {
|
||||
#include "CfgEden.hpp"
|
||||
#include "CfgEventHandlers.hpp"
|
||||
|
||||
#include "CfgAmmo.hpp"
|
||||
#include "CfgCloudlets.hpp"
|
||||
#include "CfgSFX.hpp"
|
||||
#include "CfgVehicles.hpp"
|
||||
|
@ -129,6 +129,6 @@ if (local _vehicle) then {
|
||||
if (local _vehicle) then {
|
||||
_vehicle setDamage 1;
|
||||
};
|
||||
}, [_vehicle, _effects], 4 + random 1] call CBA_fnc_waitAndExecute;
|
||||
}, [_vehicle, _effects, _positions], 3 + random 2] call CBA_fnc_waitAndExecute;
|
||||
}, _vehicle, 0.5 + random 0.3] call CBA_fnc_waitAndExecute;
|
||||
}, [_vehicle, _effects], 4 + random 20] call CBA_fnc_waitAndExecute;
|
||||
}, [_vehicle, _effects, _positions], 3 + random 15] call CBA_fnc_waitAndExecute;
|
||||
}, _vehicle, 0.5 + random 5] call CBA_fnc_waitAndExecute;
|
||||
|
75
addons/cookoff/functions/fnc_cookOffBox.sqf
Normal file
75
addons/cookoff/functions/fnc_cookOffBox.sqf
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, SilentSpike
|
||||
* Start a cook-off in the given ammo box.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Ammo box <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [_box] call ace_cookoff_fnc_cookOffBox
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_box"];
|
||||
|
||||
if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {};
|
||||
_box setVariable [QGVAR(isCookingOff), true];
|
||||
|
||||
if (local _vehicle) then {
|
||||
[QGVAR(cookOffBox), _box] call CBA_fnc_remoteEvent;
|
||||
};
|
||||
|
||||
[{
|
||||
params ["_box"];
|
||||
|
||||
// Box will start smoking
|
||||
private _smoke = "#particlesource" createVehicleLocal [0,0,0];
|
||||
_smoke setParticleClass "AmmoSmokeParticles2";
|
||||
_smoke attachTo [_box, [0,0,0]];
|
||||
|
||||
private _effects = [_smoke];
|
||||
|
||||
if (isServer) then {
|
||||
private _sound = createSoundSource ["Sound_Fire", position _box, [], 0];
|
||||
_effects pushBack _sound;
|
||||
};
|
||||
|
||||
[{
|
||||
params ["_box", "_effects"];
|
||||
|
||||
// These functions are smart and do all the cooking off work
|
||||
if (local _box) then {
|
||||
_box call FUNC(secondaryExplosions);
|
||||
if (_box getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmoCookoff)]) then {
|
||||
[_box, magazinesAmmo _box] call FUNC(detonateAmmunition);
|
||||
};
|
||||
|
||||
// This shit is busy being on fire, magazines aren't accessible/usable
|
||||
clearMagazineCargoGlobal _box;
|
||||
};
|
||||
|
||||
// Light the fire (also handles lighting)
|
||||
private _fire = "#particlesource" createVehicleLocal [0,0,0];
|
||||
_fire setParticleClass "AmmoBulletCore";
|
||||
_fire attachTo [_box, [0,0,0]];
|
||||
|
||||
_effects pushBack _fire;
|
||||
|
||||
[{
|
||||
params ["_box", "_effects"];
|
||||
|
||||
{
|
||||
deleteVehicle _x;
|
||||
} forEach _effects;
|
||||
|
||||
if (local _box) then {
|
||||
_box setDamage 1;
|
||||
};
|
||||
}, [_box, _effects], 45 + random 75] call CBA_fnc_waitAndExecute; // Give signifcant time for ammo cookoff to occur (perhaps keep the box alive until all cooked off?)
|
||||
}, [_box, _effects], 3 + random 15] call CBA_fnc_waitAndExecute;
|
||||
}, _box, 0.5 + random 5] call CBA_fnc_waitAndExecute;
|
112
addons/cookoff/functions/fnc_detonateAmmunition.sqf
Normal file
112
addons/cookoff/functions/fnc_detonateAmmunition.sqf
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Detonates ammunition from a vehicle until no ammo left
|
||||
*
|
||||
* Arguments:
|
||||
* 0: vehicle <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [_vehicle, magazinesAmmo _vehicle] call ace_cookoff_fnc_detonateAmmunition
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
#define MAX_TIME_BETWEEN_AMMO_DET 25
|
||||
|
||||
params ["_vehicle", "_magazines"];
|
||||
|
||||
if (isNull _vehicle) exitWith {}; // vehicle got deleted
|
||||
if (_magazines isEqualTo []) exitWith {}; // nothing to detonate anymore
|
||||
if (underwater _vehicle) exitWith {};
|
||||
|
||||
private _magazineIndex = floor random(count _magazines);
|
||||
private _magazine = _magazines select _magazineIndex;
|
||||
_magazine params ["_magazineClassname", "_amountOfMagazines"];
|
||||
|
||||
if (_amountOfMagazines > 0) exitWith {
|
||||
private _newMagCount = _amountOfMagazines - floor(1 + random(6));
|
||||
if (_newMagCount <= 0) then {
|
||||
_magazines deleteAt _magazineIndex;
|
||||
} else {
|
||||
_magazine set [1, _newMagCount]; // clear out the magazine
|
||||
};
|
||||
private _ammo = getText (configFile >> "CfgMagazines" >> _magazineClassname >> "ammo");
|
||||
|
||||
private _timeBetweenAmmoDetonation = (random 7) * (1 / random (_amountOfMagazines)) min MAX_TIME_BETWEEN_AMMO_DET;
|
||||
_timeBetweenAmmoDetonation = _timeBetweenAmmoDetonation max 0.1;
|
||||
|
||||
private _speedOfAmmo = getNumber (configFile >> "CfgMagazines" >> _magazineClassname >> "initSpeed");
|
||||
private _simulationTime = getNumber (configFile >> "CfgAmmo" >> _ammo >> "simulation");
|
||||
private _caliber = getNumber (configFile >> "CfgAmmo" >> _ammo >> "caliber");
|
||||
private _simType = getText (configFile >> "CfgAmmo" >> _ammo >> "simulation");
|
||||
|
||||
private _effect2pos = _vehicle selectionPosition "destructionEffect2";
|
||||
|
||||
private _spawnProjectile = {
|
||||
params ["_vehicle", "_ammo", "_speed", "_flyAway"];
|
||||
|
||||
private _spawnPos = _vehicle modelToWorld [-0.2 + (random 0.4), -0.2 + (random 0.4), random 3];
|
||||
if (_spawnPos select 2 < 0) then {
|
||||
_spawnPos set [2, 0];
|
||||
};
|
||||
private _projectile = _ammo createVehicle [0,0,0];
|
||||
_projectile setPos _spawnPos;
|
||||
if (_flyAway) then {
|
||||
private _vectorAmmo = [(-1 + (random 2)), (-1 + (random 2)), -0.2 + (random 1)];
|
||||
private _velVec = _vectorAmmo vectorMultiply _speed;
|
||||
_projectile setVectorDir _velVec;
|
||||
_projectile setVelocity _velVec;
|
||||
[ACE_player, _projectile, [1,0,0,1]] call EFUNC(frag,addTrack);
|
||||
} else {
|
||||
_projectile setDamage 1;
|
||||
};
|
||||
|
||||
_projectile;
|
||||
};
|
||||
|
||||
private _speed = random (_speedOfAmmo / 10) max 1;
|
||||
|
||||
if (toLower _simType == "shotbullet") then {
|
||||
private _sound = selectRandom [QUOTE(PATHTO_R(sounds\light_crack_close.wss)), QUOTE(PATHTO_R(sounds\light_crack_close_filtered.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close_filtered.wss))];
|
||||
playSound3D [_sound, objNull, false, (getPosASL _vehicle), 2, 1, 1250];
|
||||
|
||||
if (random 1 < 0.6) then {
|
||||
[_vehicle, _ammo, _speed, true] call _spawnProjectile;
|
||||
};
|
||||
};
|
||||
if (toLower _simType == "shotshell") then {
|
||||
private _sound = selectRandom [QUOTE(PATHTO_R(sounds\heavy_crack_close.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close_filtered.wss))];
|
||||
playSound3D [_sound, objNull, false, (getPosASL _vehicle), 2, 1, 1300];
|
||||
|
||||
if (random 1 < 0.15) then {
|
||||
[_vehicle, _ammo, _speed, random 1 < 0.15] call _spawnProjectile;
|
||||
};
|
||||
};
|
||||
if (toLower _simType == "shotgrenade") then {
|
||||
if (random 1 < 0.9) then {
|
||||
_speed = 0;
|
||||
};
|
||||
[_vehicle, _ammo, _speed, random 1 < 0.5] call _spawnProjectile;
|
||||
};
|
||||
if (toLower _simType == "shotrocket" || {toLower _simType == "shotmissile"}) then {
|
||||
if (random 1 < 0.1) then {
|
||||
private _sound = selectRandom [QUOTE(PATHTO_R(sounds\cannon_crack_close.wss)), QUOTE(PATHTO_R(sounds\cannon_crack_close_filtered.wss))];
|
||||
playSound3D [_sound, objNull, false, (getPosASL _vehicle), 3, 1, 1600];
|
||||
|
||||
[_vehicle, _ammo, _speed, random 1 < 0.3] call _spawnProjectile;
|
||||
} else {
|
||||
"ACE_ammoExplosionLarge" createvehicle (_vehicle modelToWorld _effect2pos);
|
||||
};
|
||||
};
|
||||
if (toLower _simType in ["shotdirectionalbomb", "shotilluminating", "shotmine"]) then {
|
||||
if (random 1 < 0.5) then {
|
||||
[_vehicle, _ammo, 0, false] call _spawnProjectile;
|
||||
};
|
||||
};
|
||||
|
||||
[FUNC(detonateAmmunition), [_vehicle, _magazines], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute;
|
||||
};
|
||||
[FUNC(detonateAmmunition), [_vehicle, _magazines], random 3] call CBA_fnc_waitAndExecute;
|
@ -16,7 +16,7 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_simulationType", "_thisHandleDamage"];
|
||||
_thisHandleDamage params ["_vehicle", "", "_damage", "", "_ammo", "_hitIndex"];
|
||||
_thisHandleDamage params ["_vehicle", "", "_damage", "_source", "_ammo", "_hitIndex", "_shooter"];
|
||||
|
||||
// it's already dead, who cares?
|
||||
if (damage _vehicle >= 1) exitWith {};
|
||||
@ -58,12 +58,12 @@ if (_simulationType == "car") exitWith {
|
||||
|
||||
if (_simulationType == "tank") exitWith {
|
||||
// determine ammo storage location
|
||||
private _ammoLocationHitpoint = getText (_vehicle call CBA_fnc_getObjectConfig >> QGVAR(ammoLocation));
|
||||
private _ammoLocationHitpoint = getText (_vehicle call CBA_fnc_getObjectConfig >> QGVAR(ammoLocation));
|
||||
|
||||
if (_hitIndex in (GVAR(cacheTankDuplicates) getVariable (typeOf _vehicle))) then {
|
||||
_hitpoint = "#subturret";
|
||||
};
|
||||
|
||||
|
||||
// ammo was hit, high chance for cook-off
|
||||
if (_hitpoint == _ammoLocationHitpoint) then {
|
||||
if (_damage > 0.5 && {random 1 < 0.7}) then {
|
||||
@ -82,3 +82,37 @@ if (_simulationType == "tank") exitWith {
|
||||
_damage
|
||||
};
|
||||
};
|
||||
|
||||
if (_simulationType == "box") exitWith {
|
||||
if (_hitpoint == "#structural" && _damage > 0.5) then {
|
||||
// Almost always catch fire when hit by an explosive
|
||||
if (IS_EXPLOSIVE_AMMO(_ammo)) then {
|
||||
_vehicle call FUNC(cookOffBox);
|
||||
} else {
|
||||
// Need magazine to check for tracers
|
||||
private _mag = "";
|
||||
if (_source == _shooter) then {
|
||||
_mag = currentMagazine _source;
|
||||
} else {
|
||||
_mag = _source currentMagazineTurret ([_shooter] call CBA_fnc_turretPath);
|
||||
};
|
||||
private _magCfg = configFile >> "CfgMagazines" >> _mag;
|
||||
|
||||
// Magazine could have changed during flight time (just ignore if so)
|
||||
if (getText (_magCfg >> "ammo") == _ammo) then {
|
||||
// If magazine's tracer density is high enough then low chance for cook off
|
||||
private _tracers = getNumber (_magCfg >> "tracersEvery");
|
||||
if (_tracers >= 1 && {_tracers <= 4}) then {
|
||||
if (random 1 < _oldDamage*0.05) then {
|
||||
_vehicle call FUNC(cookOffBox);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// prevent destruction, let cook-off handle it if necessary
|
||||
_damage min 0.89
|
||||
} else {
|
||||
_damage
|
||||
};
|
||||
};
|
||||
|
BIN
addons/cookoff/sounds/cannon_crack_close.wss
Normal file
BIN
addons/cookoff/sounds/cannon_crack_close.wss
Normal file
Binary file not shown.
BIN
addons/cookoff/sounds/cannon_crack_close_filtered.wss
Normal file
BIN
addons/cookoff/sounds/cannon_crack_close_filtered.wss
Normal file
Binary file not shown.
BIN
addons/cookoff/sounds/heavy_crack_close.wss
Normal file
BIN
addons/cookoff/sounds/heavy_crack_close.wss
Normal file
Binary file not shown.
BIN
addons/cookoff/sounds/heavy_crack_close_filtered.wss
Normal file
BIN
addons/cookoff/sounds/heavy_crack_close_filtered.wss
Normal file
Binary file not shown.
BIN
addons/cookoff/sounds/light_crack_close.wss
Normal file
BIN
addons/cookoff/sounds/light_crack_close.wss
Normal file
Binary file not shown.
BIN
addons/cookoff/sounds/light_crack_close_filtered.wss
Normal file
BIN
addons/cookoff/sounds/light_crack_close_filtered.wss
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project name="ACE">
|
||||
<Package name="CookOff">
|
||||
<Key ID="STR_ACE_CookOff_enable_name">
|
||||
@ -31,5 +31,17 @@
|
||||
<Korean>잔해(포탑)</Korean>
|
||||
<Japanese>残骸(タレット)</Japanese>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enable_name">
|
||||
<English>Enable ammo box cook off</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enable_tooltip">
|
||||
<English>Enables cooking off of ammo boxes.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableAmmoCookoff_name">
|
||||
<English>Enable Ammunition cook off</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableAmmoCookoff_tooltip">
|
||||
<English>Enables Ammunition cook off. Fires ammunition projectiles while vehicle is on fire and has ammunition.</English>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
||||
|
@ -217,7 +217,7 @@ class CfgVehicles {
|
||||
GVAR(enabled) = 2;
|
||||
GVAR(ropeOrigins)[] = {"ropeOriginRight", "ropeOriginLeft"};
|
||||
GVAR(friesType) = "ACE_friesGantry";
|
||||
GVAR(friesAttachmentPoint)[] = {-1.07, 3.26, -0.5};
|
||||
GVAR(friesAttachmentPoint)[] = {1.07, 2.5, -0.5};
|
||||
EQUIP_FRIES_ATTRIBUTE;
|
||||
};
|
||||
class Heli_Transport_04_base_F: Helicopter_Base_H {
|
||||
|
@ -146,9 +146,16 @@ if (isServer) then {
|
||||
//systemChat format ["burn: %1", _x];
|
||||
|
||||
// --- destroy nearby static weapons and ammo boxes
|
||||
if (_x isKindOf "StaticWeapon" || {_x isKindOf "ReammoBox_F"} || {_x isKindOf "ACE_RepairItem_Base"}) then {
|
||||
if (_x isKindOf "StaticWeapon" || {_x isKindOf "ACE_RepairItem_Base"}) then {
|
||||
_x setDamage 1;
|
||||
};
|
||||
if (_x isKindOf "ReammoBox_F") then {
|
||||
if ("ace_cookoff" call EFUNC(common,isModLoaded) && {EGVAR(cookoff,enable)}) then {
|
||||
_x call EFUNC(cookoff,cookOffBox);
|
||||
} else {
|
||||
_x setDamage 1;
|
||||
};
|
||||
};
|
||||
|
||||
// --- delete nearby ground weapon holders
|
||||
if (_x isKindOf "WeaponHolder" || {_x isKindOf "WeaponHolderSimulated"}) then {
|
||||
|
7
addons/laser/ACE_Settings.hpp
Normal file
7
addons/laser/ACE_Settings.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
class ACE_Settings {
|
||||
class GVAR(dispersionCount) {
|
||||
value = 2;
|
||||
typeName = "SCALAR";
|
||||
displayName = CSTRING(dispersionCount_displayName);
|
||||
};
|
||||
};
|
@ -1,4 +1,3 @@
|
||||
|
||||
class Extended_PreStart_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_preStart));
|
||||
@ -7,20 +6,13 @@ class Extended_PreStart_EventHandlers {
|
||||
|
||||
class Extended_PreInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_pre_init));
|
||||
init = QUOTE(call COMPILE_FILE(XEH_preInit));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_PostInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_post_init));
|
||||
init = QUOTE(call COMPILE_FILE(XEH_postInit));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_Init_EventHandlers {
|
||||
class LaserTargetBase {
|
||||
class ADDON {
|
||||
init = QUOTE(_this call DFUNC(laser_init));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,44 +1,31 @@
|
||||
class CfgVehicles {
|
||||
class All;
|
||||
|
||||
class LaserTarget: All {
|
||||
// @TODO: Changing the model and simulation hides it, but THEN IT DOESNT SPAWN WTF!?
|
||||
model = "\A3\Weapons_F\empty.p3d";
|
||||
destrType = "DestructNo";
|
||||
simulation = "LaserTarget";
|
||||
// model = "\A3\Weapons_F\empty.p3d";
|
||||
|
||||
class EventHandlers {
|
||||
init = QUOTE(_this call FUNC(laser_init));
|
||||
class ADDON {
|
||||
init = QUOTE(_this call FUNC(handleLaserTargetCreation));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Visual laserTarget override
|
||||
class ACE_LaserTarget_Visual : LaserTarget {
|
||||
simulation = "LaserTarget";
|
||||
model = "\A3\Weapons_f\laserTgt.p3d";
|
||||
// laserTarget fails if the turret does not have "primaryGunner" config
|
||||
// This only effects the indfor strider who's commander is not the primaryGunner
|
||||
class LandVehicle;
|
||||
class Car: LandVehicle {
|
||||
class NewTurret;
|
||||
};
|
||||
|
||||
// Vehicle lockable configurations
|
||||
|
||||
class AllVehicles;
|
||||
class Air: AllVehicles {
|
||||
class Turrets;
|
||||
};
|
||||
|
||||
class Helicopter: Air {
|
||||
class Car_F: Car {
|
||||
class Turrets {
|
||||
class MainTurret;
|
||||
class MainTurret: NewTurret {};
|
||||
};
|
||||
};
|
||||
|
||||
class Helicopter_Base_F: Helicopter {};
|
||||
|
||||
class Heli_Attack_01_base_F: Helicopter_Base_F {};
|
||||
|
||||
class B_Heli_Attack_01_F: Heli_Attack_01_base_F {
|
||||
class MRAP_03_base_F: Car_F {
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {
|
||||
GVAR(CanLockLaser) = 1; // Enable laser locking selection
|
||||
class CommanderTurret: MainTurret {
|
||||
primaryGunner = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -10,3 +10,5 @@ The people responsible for merging changes to this component or answering potent
|
||||
|
||||
- [walterpearce](https://github.com/walterpearce)
|
||||
- [NouberNou](https://github.com/NouberNou)
|
||||
- [esteldunedain](https://github.com/esteldunedain)
|
||||
- [PabstMirror](https://github.com/PabstMirror)
|
||||
|
@ -1,26 +1,15 @@
|
||||
|
||||
PREP(rotateVectLineGetMap);
|
||||
PREP(rotateVectLine);
|
||||
PREP(shootRay);
|
||||
PREP(shootCone);
|
||||
PREP(checkLos);
|
||||
|
||||
PREP(findStrongestRay);
|
||||
|
||||
PREP(onLaserDesignatorDraw);
|
||||
|
||||
PREP(seekerFindLaserSpot);
|
||||
PREP(laserOn);
|
||||
PREP(addLaserTarget);
|
||||
PREP(dev_drawVisibleLaserTargets);
|
||||
PREP(findLaserSource);
|
||||
PREP(handleLaserTargetCreation);
|
||||
PREP(keyLaserCodeChange);
|
||||
PREP(laserOff);
|
||||
PREP(handleLaserOn);
|
||||
PREP(handleLaserOff);
|
||||
|
||||
PREP(drawVisibleLaserTargets);
|
||||
|
||||
PREP(laser_init);
|
||||
PREP(vanillaLaserSeekerHandler);
|
||||
PREP(laserOn);
|
||||
PREP(laserTargetPFH);
|
||||
|
||||
PREP(unitTurretCanLockLaser);
|
||||
PREP(keyLaserCodeUp);
|
||||
PREP(keyLaserCodeDown);
|
||||
PREP(onLaserDesignatorDraw);
|
||||
PREP(rotateVectLine);
|
||||
PREP(rotateVectLineGetMap);
|
||||
PREP(seekerFindLaserSpot);
|
||||
PREP(shootCone);
|
||||
PREP(shootRay);
|
||||
|
23
addons/laser/XEH_postInit.sqf
Normal file
23
addons/laser/XEH_postInit.sqf
Normal file
@ -0,0 +1,23 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
#include "initKeybinds.sqf"
|
||||
|
||||
// Global Laser EHs
|
||||
["ace_laserOn", {
|
||||
params ["_uuid", "_args"];
|
||||
TRACE_2("ace_laserOn eh",_uuid,_args);
|
||||
[GVAR(laserEmitters), _uuid, _args] call CBA_fnc_hashSet;
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
||||
["ace_laserOff", {
|
||||
params ["_uuid"];
|
||||
TRACE_1("ace_laserOn eh",_uuid);
|
||||
if ([GVAR(laserEmitters), _uuid] call CBA_fnc_hashHasKey) then {
|
||||
[GVAR(laserEmitters), _uuid] call CBA_fnc_hashRem;
|
||||
};
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
||||
// Shows detector and mine posistions in 3d when debug is on
|
||||
#ifdef DRAW_LASER_INFO
|
||||
addMissionEventHandler ["Draw3D", {_this call FUNC(dev_drawVisibleLaserTargets)}];
|
||||
#endif
|
@ -1,7 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
#include "initKeybinds.sqf"
|
||||
|
||||
["ace_laserOn", {_this call DFUNC(handleLaserOn)}] call CBA_fnc_addEventHandler;
|
||||
["ace_laserOff", {_this call DFUNC(handleLaserOff)}] call CBA_fnc_addEventHandler;
|
||||
|
@ -4,13 +4,13 @@ ADDON = false;
|
||||
|
||||
#include "XEH_PREP.hpp"
|
||||
|
||||
GVAR(VanillaLasers) = [];
|
||||
|
||||
// Laser default variables
|
||||
ACE_DEFAULT_LASER_CODE = 1001;
|
||||
ACE_DEFAULT_LASER_CODE = 1111;
|
||||
ACE_DEFAULT_LASER_WAVELENGTH = 1550;
|
||||
ACE_DEFAULT_LASER_BEAMSPREAD = 1;
|
||||
|
||||
GVAR(laserEmitters) = [] call CBA_fnc_hashCreate;
|
||||
GVAR(trackedLaserTargets) = [];
|
||||
GVAR(pfehID) = -1;
|
||||
|
||||
ADDON = true;
|
@ -13,6 +13,7 @@ class CfgPatches {
|
||||
};
|
||||
};
|
||||
|
||||
#include "ACE_Settings.hpp"
|
||||
#include "CfgEventhandlers.hpp"
|
||||
#include "CfgVehicles.hpp"
|
||||
#include "CfgWeapons.hpp"
|
||||
|
59
addons/laser/functions/fnc_addLaserTarget.sqf
Normal file
59
addons/laser/functions/fnc_addLaserTarget.sqf
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Author: esteldunedain
|
||||
* Adds a vanilla laser target to the tracker PFH and globaly turns it on
|
||||
*
|
||||
* Argument:
|
||||
* 0: TargetObject (vanilla laser) <OBJECT>
|
||||
* 1: Vehicle <OBJECT>
|
||||
*
|
||||
* Return value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [laserTarget player, player] call ace_laser_fnc_addLaserTarget;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_targetObject", "_vehicle"];
|
||||
TRACE_2("params",_targetObject,_vehicle);
|
||||
|
||||
// Get the designator variables, or use defaults
|
||||
private _waveLength = _vehicle getVariable [QEGVAR(laser,waveLength), ACE_DEFAULT_LASER_WAVELENGTH];
|
||||
private _laserCode = _vehicle getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE];
|
||||
private _beamSpread = _vehicle getVariable [QEGVAR(laser,beamSpread), ACE_DEFAULT_LASER_BEAMSPREAD];
|
||||
TRACE_3("codes",_waveLength,_laserCode,_beamSpread);
|
||||
|
||||
// Laser method is the method ACE_Laser will use to determine from where to where it should project the designator cone
|
||||
_vehicle setVariable [QGVAR(targetObject), _targetObject, true];
|
||||
|
||||
private _laserMethod = QFUNC(findLaserSource);
|
||||
|
||||
private _vehicleSourceSelection = "";
|
||||
if (_vehicle isKindOf "CaManBase") then {
|
||||
_vehicleSourceSelection = "pilot";
|
||||
} else {
|
||||
{ // Go through turrets on vehicle and find the laser
|
||||
private _turretPath = _x;
|
||||
{
|
||||
if ((getNumber (configFile >> "CfgWeapons" >> _x >> "laser")) > 0) exitWith {
|
||||
_vehicleSourceSelection = getText (([_vehicle, _turretPath] call CBA_fnc_getTurret) >> "memoryPointGunnerOptics");
|
||||
TRACE_3("",_turretPath,_x,_vehicleSourceSelection);
|
||||
};
|
||||
} forEach (_vehicle weaponsTurret _turretPath);
|
||||
} forEach (allTurrets [_vehicle, true]);
|
||||
};
|
||||
|
||||
private _methodArgs = [_vehicleSourceSelection];
|
||||
|
||||
TRACE_6("Laser on:",_vehicle,_laserMethod,_waveLength,_laserCode,_beamSpread,_methodArgs);
|
||||
private _laserUuid = [_vehicle, _vehicle, _laserMethod, _waveLength, _laserCode, _beamSpread, _methodArgs] call FUNC(laserOn);
|
||||
|
||||
GVAR(trackedLaserTargets) pushBack [_targetObject, _vehicle, _laserUuid];
|
||||
TRACE_1("",GVAR(trackedLaserTargets));
|
||||
|
||||
if (GVAR(pfehID) == -1) then {
|
||||
TRACE_1("starting pfeh",count GVAR(trackedLaserTargets));
|
||||
GVAR(pfehID) = [DFUNC(laserTargetPFH), 0, []] call CBA_fnc_addPerFrameHandler;
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_pos1", "_pos2", "_designator", "_seeker"];
|
||||
|
||||
private _spacing = 100;
|
||||
if((count _this) > 4) then {
|
||||
_spacing = _this select 4;
|
||||
};
|
||||
|
||||
private _return = true;
|
||||
private _vectorTo = [_pos2, _pos1] call BIS_fnc_vectorFromXToY;
|
||||
|
||||
private _x = (_vectorTo select 0)*0.25;
|
||||
private _y = (_vectorTo select 1)*0.25;
|
||||
private _z = (_vectorTo select 2)*0.25;
|
||||
|
||||
_pos2 = [(_pos2 select 0) + _x, (_pos2 select 1) + _y, (_pos2 select 2) + _z];
|
||||
|
||||
// player sideChat format["new los check"];
|
||||
if(terrainIntersect [_pos2, _pos1]) then {
|
||||
_return = false;
|
||||
} else {
|
||||
if(lineIntersects [_pos2, _pos1]) then { // should take as arguments and add to this command objects to exclude - target and observer
|
||||
// player sideChat format["with: %1", lineIntersectsWith [_pos1, _pos2]];
|
||||
_return = false;
|
||||
};
|
||||
};
|
||||
_return;
|
61
addons/laser/functions/fnc_dev_drawVisibleLaserTargets.sqf
Normal file
61
addons/laser/functions/fnc_dev_drawVisibleLaserTargets.sqf
Normal file
@ -0,0 +1,61 @@
|
||||
// Dev Debug Function
|
||||
// Displays lasers and attempts to lock on to codes 1111 and 1112 from a target vehicle's view
|
||||
// On Screen Debug:
|
||||
// Red - Vanilla Laser Targets
|
||||
// Yellow - Array (vehicle pos/weapon) Laser Targets
|
||||
// Green - Rays
|
||||
// Blue - Seeker Locks
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
// Try searching for lasers from a given vehicle position [BLUE]:
|
||||
private _seekerVehicle = vehicle ace_player;
|
||||
private _testSeekerPosASL = AGLtoASL (_seekerVehicle modelToWorldVisual [0,0,1]);
|
||||
private _testSeekerDir = vectorDirVisual _seekerVehicle;
|
||||
{
|
||||
private _code = _x;
|
||||
private _results = [_testSeekerPosASL, _testSeekerDir, 45, [1550,1550], _code, _seekerVehicle] call FUNC(seekerFindLaserSpot);
|
||||
private _resultPos = _results select 0;
|
||||
if (!isNil "_resultPos") then {
|
||||
// Draw lock results
|
||||
drawLine3D [ASLtoAGL _testSeekerPosASL, ASLtoAGL _resultPos, [0,0,1,1]];
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [0,0,1,1], (ASLtoAGL _resultPos), 1.5, 1.5, 45, format ["%1 from %2", _code, _results select 1], 0.5, 0.025, "TahomaB"];
|
||||
};
|
||||
} forEach [1111, 1112]; // Scan at codes 1111 and 1112
|
||||
|
||||
|
||||
// Draw all lasers
|
||||
[GVAR(laserEmitters), {
|
||||
// TRACE_2("",_key,_value);
|
||||
_value params ["_obj", "_owner", "_laserMethod", "_waveLength", "_laserCode", "_beamSpread"];
|
||||
|
||||
// Draw vanila lasers [RED]
|
||||
if (_laserMethod isEqualTo QFUNC(findLaserSource)) then { // Normal vanilla laserTarget func
|
||||
private _targetObject = _obj getVariable [QGVAR(targetObject), objNull];
|
||||
private _targetPosASL = getPosASL _targetObject;
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], (ASLtoAGL _targetPosASL), 0.5, 0.5, 0, "", 0.5, 0.025, "TahomaB"];
|
||||
|
||||
(_value call FUNC(findLaserSource)) params ["_laserPosASL", "_laserDir"];
|
||||
private _resultsRay = [_laserPosASL, _laserDir, _obj] call FUNC(shootRay);
|
||||
|
||||
private _rayPos = _resultsRay select 0;
|
||||
if (isNil "_rayPos") then {
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], (ASLtoAGL _targetPosASL), 2, 2, 0, "Nil Ray", 0.5, 0.025, "TahomaB"];
|
||||
} else {
|
||||
private _diff = _rayPos vectorDistance (getPosASL _targetObject); // Diff from ray position compared to actual
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], (ASLtoAGL _rayPos), 2, 2, 0, format ["Diff %1",_diff], 0.5, 0.025, "TahomaB"];
|
||||
};
|
||||
};
|
||||
// Draw array weapon lasers [YELLOW]
|
||||
if ((_laserMethod isEqualType []) && {(count _laserMethod) == 2}) then {
|
||||
_laserMethod params ["_modelPosition", "_weaponName"];
|
||||
private _laserPosASL = AGLtoASL (_obj modelToWorldVisual _modelPosition);
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,1,0,1], (ASLtoAGL _laserPosASL), 0.5, 0.5, 0, _weaponName, 0.5, 0.025, "TahomaB"];
|
||||
private _laserDir = _obj weaponDirection _weaponName;
|
||||
private _resultsRay = [_laserPosASL, _laserDir, _obj] call FUNC(shootRay);
|
||||
private _rayPos = _resultsRay select 0;
|
||||
if (!isNil "_rayPos") then {
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,1,0,1], (ASLtoAGL _rayPos), 2, 2, 0, _weaponName, 0.5, 0.025, "TahomaB"];
|
||||
};
|
||||
};
|
||||
}] call CBA_fnc_hashEachPair;
|
@ -1,9 +0,0 @@
|
||||
// This is a debug function for displaying visible lasers for ourselves
|
||||
#include "script_component.hpp"
|
||||
|
||||
INFO("Laser Emitter Dump");
|
||||
|
||||
{
|
||||
INFO_1(" %1", _x);
|
||||
INFO_1(" %1",[ARR_2(GVAR(laserEmitters),_x)] call CBA_fnc_hashGet);
|
||||
} forEach (GVAR(laserEmitters) select 1);
|
41
addons/laser/functions/fnc_findLaserSource.sqf
Normal file
41
addons/laser/functions/fnc_findLaserSource.sqf
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Author: esteldunedain
|
||||
* Handler function for finding position and direction of a vanilla laser.
|
||||
*
|
||||
* Argument:
|
||||
* 0: Vehicle (shooter of laser) <OBJECT>
|
||||
* 6: Method Args <ARRAY>
|
||||
* 0: Laser Source selection on Vehicle
|
||||
*
|
||||
* Return value:
|
||||
* [position, direction]
|
||||
*
|
||||
* Example:
|
||||
* [player, x,x,x,x,x, ["pilot"]] call ace_laser_fnc_findLaserSource;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_vehicle", "", "", "", "", "", "_methodArgs"];
|
||||
_methodArgs params ["_ownerSelection"];
|
||||
|
||||
// Get the laser target object stored in the unit
|
||||
private _targetObject = _vehicle getVariable [QGVAR(targetObject), objNull];
|
||||
private _targetPos = getPosASL _targetObject;
|
||||
if (surfaceIsWater _targetPos && {(_targetPos select 2) < 0}) then {
|
||||
// Vanilla lasers seem to give position at ocean floor heigh, even though the x and y are correct??
|
||||
_targetPos set [2, 0.25];
|
||||
};
|
||||
|
||||
private _povPos = AGLtoASL (_vehicle modelToWorldVisual (_vehicle selectionPosition _ownerSelection));
|
||||
private _povDir = _povPos vectorFromTo _targetPos;
|
||||
|
||||
TRACE_4("",_vehicle,_targetObject,_povPos,_povDir);
|
||||
|
||||
if(isNil "_povPos" || isNil "_povDir") exitWith {
|
||||
WARNING_2("bad data [%1][%2]",_povPos,_povDir);
|
||||
[-1,-1]
|
||||
};
|
||||
|
||||
[_povPos, _povDir]
|
@ -1,48 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_list", "_checkPos"];
|
||||
private _spots = [];
|
||||
private _outliers = [];
|
||||
private _spot = [];
|
||||
(_list select 0) params ["_testPos"];
|
||||
{
|
||||
_x params ["_samplePos"];
|
||||
if(!lineIntersects [_samplePos, _checkPos] && {!terrainIntersectASL [_samplePos, _checkPos]}) then {
|
||||
if(_samplePos distance _testPos < 2) then {
|
||||
_spot pushBack _samplePos;
|
||||
} else {
|
||||
_outliers pushBack _samplePos;
|
||||
};
|
||||
};
|
||||
} forEach _list;
|
||||
_spots pushBack _spot;
|
||||
|
||||
if(count _outliers > 0) then {
|
||||
for "_i" from 1 to 3 do {
|
||||
private _remainingSpots = _outliers;
|
||||
_outliers = [];
|
||||
_spot = [];
|
||||
_testPos = (_remainingSpots select 0);
|
||||
{
|
||||
private _samplePos = _x;
|
||||
if(!lineIntersects [_samplePos, _checkPos] && {!terrainIntersectASL [_samplePos, _checkPos]}) then {
|
||||
if(_samplePos distance _testPos < 2) then {
|
||||
_spot pushBack _samplePos;
|
||||
} else {
|
||||
_outliers pushBack _samplePos;
|
||||
};
|
||||
};
|
||||
} forEach _remainingSpots;
|
||||
_spots pushBack _spot;
|
||||
};
|
||||
};
|
||||
private _largest = 0;
|
||||
private _largestSpot = [];
|
||||
{
|
||||
if(count _x > _largest) then {
|
||||
_largest = count _x;
|
||||
_largestSpot = _x;
|
||||
};
|
||||
} forEach _spots;
|
||||
// player sideChat format["g: %1", _spots];
|
||||
_largestSpot select (random (floor(count _largestSpot)));
|
@ -1,7 +0,0 @@
|
||||
//fnc_handleLaserOff.sqf
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_uuid"];
|
||||
if ([GVAR(laserEmitters), _uuid] call CBA_fnc_hashHasKey) then {
|
||||
[GVAR(laserEmitters), _uuid] call CBA_fnc_hashRem;
|
||||
};
|
@ -1,5 +0,0 @@
|
||||
//fnc_handleLaserOn.sqf
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_uuid", "_args"];
|
||||
[GVAR(laserEmitters), _uuid, _args] call CBA_fnc_hashSet;
|
41
addons/laser/functions/fnc_handleLaserTargetCreation.sqf
Normal file
41
addons/laser/functions/fnc_handleLaserTargetCreation.sqf
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Author: esteldunedain
|
||||
* Associates a newly created laser target to it's owner
|
||||
*
|
||||
* Argument:
|
||||
* 0: Vanilla Laser (base type LaserTarget) <OBJECT>
|
||||
*
|
||||
* Return value:
|
||||
* None
|
||||
*
|
||||
* Return value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [laserTarget player] call ace_laser_fnc_handleLaserTargetCreation;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
TRACE_1("params",_this);
|
||||
[{
|
||||
params ["_targetObject"];
|
||||
|
||||
// Only handle locally created lasers
|
||||
if(!(local _targetObject)) exitWith {TRACE_1("not local",_targetObject);};
|
||||
|
||||
private _owners = allUnits select {(lasertarget _x) == _targetObject};
|
||||
if (count _owners == 1) exitWith {
|
||||
TRACE_2("Laser target owner [allUnits]", _targetObject, _owners select 0);
|
||||
[_targetObject, _owners select 0] call FUNC(addLaserTarget);
|
||||
};
|
||||
|
||||
_owners = vehicles select {(lasertarget _x) == _targetObject};
|
||||
if (count _owners == 1) exitWith {
|
||||
TRACE_2("Laser target owner [vehicles]", _targetObject, _owners select 0);
|
||||
[_targetObject, _owners select 0] call FUNC(addLaserTarget);
|
||||
};
|
||||
|
||||
TRACE_1("Laser target doesn't have owner", _targetObject);
|
||||
}, _this] call CBA_fnc_execNextFrame;
|
59
addons/laser/functions/fnc_keyLaserCodeChange.sqf
Normal file
59
addons/laser/functions/fnc_keyLaserCodeChange.sqf
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Change the laser key code (both seeker and transmitter)
|
||||
*
|
||||
* Argument:
|
||||
* 0: Change in code <NUMBER>
|
||||
*
|
||||
* Return value:
|
||||
* Key Handled <BOOL>
|
||||
|
||||
* Example:
|
||||
* [1] call ace_laser_fnc_keyLaserCodeChange;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params [["_codeChange", 0, [0]]];
|
||||
|
||||
TRACE_1("params",_codeChange);
|
||||
|
||||
if ((!alive ACE_player) || {!([ACE_player, vehicle ACE_player, []] call EFUNC(common,canInteractWith))}) exitWith {false};
|
||||
|
||||
private _currentShooter = objNull;
|
||||
private _currentWeapon = "";
|
||||
|
||||
if (ACE_player call CBA_fnc_canUseWeapon) then {
|
||||
_currentShooter = ACE_player;
|
||||
_currentWeapon = currentWeapon ACE_player;
|
||||
} else {
|
||||
_currentShooter = vehicle ACE_player;
|
||||
private _turret = [ACE_player] call ace_common_fnc_getTurretIndex;
|
||||
_currentWeapon = _currentShooter currentWeaponTurret _turret;
|
||||
};
|
||||
|
||||
TRACE_2("",_currentShooter,_currentWeapon);
|
||||
if ((getNumber (configFile >> "CfgWeapons" >> _currentWeapon >> "laser")) == 0) exitWith {false};
|
||||
|
||||
private _oldLaserCode = _currentShooter getVariable [QGVAR(code), ACE_DEFAULT_LASER_CODE];
|
||||
private _newLaserCode = _oldLaserCode;
|
||||
|
||||
// "Four-digit code equipment settings range from 1111 to 1788"
|
||||
// While there is a 0 or 9 in code, keep adding change
|
||||
|
||||
if (((_codeChange < 0) && {_oldLaserCode > ACE_DEFAULT_LASER_CODE}) || {(_codeChange > 0) && {_oldLaserCode < 1788}}) then {
|
||||
_newLaserCode = _oldLaserCode + _codeChange;
|
||||
while {(((str _newLaserCode) find "0") >= 0) || {((str _newLaserCode) find "9") >= 0}} do {
|
||||
_newLaserCode = _newLaserCode + _codeChange;
|
||||
};
|
||||
};
|
||||
|
||||
TRACE_2("",_oldLaserCode,_newLaserCode);
|
||||
|
||||
if (_oldLaserCode != _newLaserCode) then {
|
||||
_currentShooter setVariable [QGVAR(code), _newLaserCode, false];
|
||||
};
|
||||
[format ["%1: %2", localize LSTRING(laserCode), _newLaserCode]] call EFUNC(common,displayTextStructured);
|
||||
|
||||
true
|
@ -1,12 +0,0 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
private ["_oldLaserCode", "_laserCode"];
|
||||
|
||||
_oldLaserCode = ACE_player getVariable [QGVAR(code), ACE_DEFAULT_LASER_CODE];
|
||||
if(_oldLaserCode > ACE_DEFAULT_LASER_CODE) then {
|
||||
_laserCode = _oldLaserCode - 1;
|
||||
ACE_player setVariable [QGVAR(code), _laserCode, false];
|
||||
};
|
||||
if(_laserCode != _oldLaserCode) then {
|
||||
[format ["%1: %2", localize LSTRING(laserCode), _laserCode]] call EFUNC(common,displayTextStructured);
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
private ["_oldLaserCode", "_laserCode"];
|
||||
|
||||
_oldLaserCode = ACE_player getVariable [QGVAR(code), ACE_DEFAULT_LASER_CODE];
|
||||
_laserCode = _oldLaserCode + 1;
|
||||
ACE_player setVariable [QGVAR(code), _laserCode, false];
|
||||
if(_laserCode != _oldLaserCode) then {
|
||||
[format ["%1: %2", localize LSTRING(laserCode), _laserCode]] call EFUNC(common,displayTextStructured);
|
||||
};
|
@ -3,13 +3,20 @@
|
||||
* Turn a laser designator off.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: UUID (from laserOn) <string>
|
||||
* 0: UUID (from laserOn) <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* Return value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* ["yourLaserUID"] call ace_laser_fnc_laserOff;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_uuid"];
|
||||
|
||||
TRACE_1("Sending Global Laser Off Event",_uuid);
|
||||
|
||||
["ace_laserOff", [_uuid]] call CBA_fnc_globalEvent;
|
||||
|
@ -3,20 +3,33 @@
|
||||
* Turn a laser designator on.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Emitter <object>
|
||||
* 1: Owner <object>
|
||||
* 2: Method, can be code, which emitter and owner are passed to, a string function name, an array with a position memory point and weapon name, or an array with a position memory point, a vector begining memory point, and vector ending memory point.
|
||||
* 3: Wavelength (1550nm is common eye safe) <number>
|
||||
* 4: Laser code <number>
|
||||
* 5: Beam divergence (in mils off beam center).
|
||||
* 0: Emitter <OBJECT>
|
||||
* 1: Owner <OBJECT>
|
||||
* 2: Method, can be code, which emitter and owner are passed to, a string function name, an array with a position memory point and weapon name, or an array with a position memory point, a vector begining memory point, and vector ending memory point. <STRING><CODE><ARRAY>
|
||||
* 3: Wavelength (1550nm is common eye safe) <NUMBER>
|
||||
* 4: Laser code <NUMBER>
|
||||
* 5: Beam divergence (in mils off beam center). <NUMBER>
|
||||
* 6: Method Args <OPTIONAL><ANY>
|
||||
*
|
||||
* Return Value:
|
||||
* String, UUID for sending to laserOff function.
|
||||
* <String> UUID for sending to laserOff function.
|
||||
*
|
||||
* Example:
|
||||
* [hmg, hmg, [[0,0,1], "HMG_static"], 1550, 1111, 1] call ace_laser_fnc_laserOn;
|
||||
* [player, player, "ace_laser_fnc_findLaserSource", 1550, 1111, 1, ["pilot"]] call ace_laser_fnc_laserOn;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
// params [["_emitter", objNull, [objNull]],["_owner", objNull, [objNull]],["_method", "", ["", {}, []]],["_wavelength", 0, [0]],["_code", 0, [0]],["_beamSpread", 0, [0]],"_methodArgs"];
|
||||
|
||||
private _uuid = format["%1%2%3", floor diag_tickTime, floor random 1000, floor random 10000];
|
||||
private _args = [_uuid, _this];
|
||||
|
||||
TRACE_2("Sending Global Laser On Event",_uuid,_this);
|
||||
|
||||
["ace_laserOn", _args] call CBA_fnc_globalEvent;
|
||||
|
||||
_uuid;
|
||||
|
@ -1,27 +1,40 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
/*
|
||||
* Author: esteldunedain
|
||||
* Maintains the tracked lasers, deleting any laser that is turned off
|
||||
*
|
||||
* Argument:
|
||||
* PFEH Args
|
||||
*
|
||||
* Return value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [[], 1]] call ace_laser_fnc_laserTargetPFH;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
TRACE_1("enter", _this);
|
||||
|
||||
//TRACE_1("enter", _this);
|
||||
params ["_args"];
|
||||
_args params ["_laserTarget", "_shooter", "_uuid"];
|
||||
params ["", "_pfhuid"];
|
||||
|
||||
if(isNull _laserTarget || !alive _shooter) exitWith {
|
||||
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
|
||||
REM(GVAR(VanillaLasers), _laserTarget);
|
||||
GVAR(trackedLaserTargets) = GVAR(trackedLaserTargets) select {
|
||||
_x params ["_targetObject", "_owner", "_laserUuid"];
|
||||
if ((isNull _targetObject) ||
|
||||
{!(alive _targetObject)} ||
|
||||
{isNull _owner} ||
|
||||
{!(alive _owner)}) then {
|
||||
|
||||
// Remove laseron
|
||||
[_uuid] call FUNC(laserOff);
|
||||
// Turn off the laser in ace_laser
|
||||
[_laserUuid] call FUNC(laserOff);
|
||||
TRACE_1("Laser off:", _laserUuid);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
// Iconize the location of the actual laserTarget
|
||||
_pos = getPosASL _laserTarget;
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], (ASLtoATL _pos), 0.75, 0.75, 0, "", 0.5, 0.025, "TahomaB"];
|
||||
|
||||
{
|
||||
drawLine3D [ASLtoATL (_x select 0), ASLtoATL (_x select 1), (_x select 2)];
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", (_x select 2), ASLtoATL (_x select 1), 0.75, 0.75, 0, "", 0.5, 0.025, "TahomaB"];
|
||||
} forEach DRAW_LINES;
|
||||
DRAW_LINES = [];
|
||||
#endif
|
||||
if (GVAR(trackedLaserTargets) isEqualTo []) then {
|
||||
TRACE_1("ending pfeh",count GVAR(trackedLaserTargets));
|
||||
[_pfhuid] call CBA_fnc_removePerFrameHandler;
|
||||
GVAR(pfehID) = -1;
|
||||
};
|
||||
|
@ -1,33 +0,0 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
TRACE_1("enter", _this);
|
||||
|
||||
PARAMS_1(_laserTarget);
|
||||
private ["_uuid"];
|
||||
|
||||
// Add the target to the global targets array
|
||||
// Everyone tracks them
|
||||
// Add the laser localized to the laser array, and give it the default localized code
|
||||
PUSH(GVAR(VanillaLasers), _laserTarget);
|
||||
|
||||
// Check the vehicle, otherwise use the default
|
||||
_laserTarget setVariable [QGVAR(code), ACE_DEFAULT_LASER_CODE, false];
|
||||
_laserTarget setVariable [QGVAR(beamSpread), ACE_DEFAULT_LASER_BEAMSPREAD, false];
|
||||
_laserTarget setVariable [QGVAR(waveLength), ACE_DEFAULT_LASER_WAVELENGTH, false];
|
||||
|
||||
// Clean the lasers of any null objects while we are here
|
||||
REM(GVAR(VanillaLasers), objNull);
|
||||
|
||||
if(!(local _laserTarget)) exitWith { };
|
||||
|
||||
// The target is local, so its on this client
|
||||
if(!isDedicated) then {
|
||||
// @TODO: Get ownership variables and set them on the vehicle
|
||||
|
||||
_uuid = [(vehicle ACE_player), ACE_player, QFUNC(vanillaLaserSeekerHandler), ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_CODE, ACE_DEFAULT_LASER_BEAMSPREAD] call FUNC(laserOn);
|
||||
_laserTarget setVariable [QGVAR(uuid), _uuid, false];
|
||||
[FUNC(laserTargetPFH), 0, [_laserTarget, ACE_player, _uuid]] call CBA_fnc_addPerFrameHandler;
|
||||
} else {
|
||||
// server side ownership of laser
|
||||
_laserTarget setVariable [QGVAR(owner), nil, true];
|
||||
};
|
@ -1,15 +1,28 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
/*
|
||||
* Author: Nou
|
||||
* Update distance when rangefinder laser is on
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_laser_fnc_onLaserDesignatorDraw
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
private ["_laserCode"];
|
||||
|
||||
_laserCode = ACE_player getVariable[QGVAR(code), ACE_DEFAULT_LASER_CODE];
|
||||
if(!isNil "_laserCode") then {
|
||||
private _laserCode = ACE_player getVariable[QGVAR(code), ACE_DEFAULT_LASER_CODE];
|
||||
if (!isNil "_laserCode") then {
|
||||
__LaserDesignatorIGUI_LaserCode ctrlSetText format["Code: %1", [_laserCode, 4, 0, false] call CBA_fnc_formatNumber];
|
||||
};
|
||||
|
||||
if(! (ctrlShown __LaserDesignatorIGUI_LaserOn) ) then {
|
||||
if (! (ctrlShown __LaserDesignatorIGUI_LaserOn) ) then {
|
||||
// TODO: hide distance
|
||||
__LaserDesignatorIGUI_ACE_Distance ctrlSetText "----";
|
||||
} else {
|
||||
__LaserDesignatorIGUI_ACE_Distance ctrlSetText (ctrlText __LaserDesignatorIGUI_CA_Distance);
|
||||
};
|
||||
};
|
||||
|
@ -1,16 +1,9 @@
|
||||
#include "script_component.hpp"
|
||||
private ["_d", "_map", "_p", "_theta", "_u"];
|
||||
_map = _this select 0;
|
||||
_theta = _this select 1;
|
||||
|
||||
_p = _map select 0;
|
||||
_p1 = _map select 1;
|
||||
_p2 = _map select 2;
|
||||
|
||||
_q1 = +(_map select 3);
|
||||
_q2 = +(_map select 4);
|
||||
_u = _map select 5;
|
||||
_d = _map select 6;
|
||||
params ["_map", "_theta"];
|
||||
_map params ["_p", "_p1", "_p2", "_q1", "_q2", "_u", "_d"];
|
||||
_q1 = +_q1;
|
||||
_q2 = +_q2;
|
||||
|
||||
/* Step 4 */
|
||||
_q2 set[0, (_q1 select 0) * cos(_theta) - (_q1 select 1) * sin(_theta)];
|
||||
@ -33,4 +26,4 @@ if (_d != 0) then {
|
||||
|
||||
/* Inverse of step 1 */
|
||||
_q1 = _q2 vectorAdd _p1;
|
||||
_q1;
|
||||
_q1;
|
||||
|
@ -1,17 +1,14 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_p", "_theta", "_p1", "_p2", "_q1", "_q2", "_u", "_d"];
|
||||
_p = _this select 0;
|
||||
_p1 = _this select 1;
|
||||
_p2 = _this select 2;
|
||||
params ["_p", "_p1", "_p2"];
|
||||
|
||||
_q2 = [];
|
||||
private _q2 = [];
|
||||
|
||||
/* Step 1 */
|
||||
_q1 = _p vectorDiff _p1;
|
||||
_u = _p2 vectorDiff _p1;
|
||||
private _q1 = _p vectorDiff _p1;
|
||||
private _u = _p2 vectorDiff _p1;
|
||||
_u = vectorNormalized _u;
|
||||
_d = sqrt((_u select 1)*(_u select 1) + (_u select 2)*(_u select 2));
|
||||
private _d = sqrt((_u select 1)*(_u select 1) + (_u select 2)*(_u select 2));
|
||||
|
||||
/* Step 2 */
|
||||
if (_d != 0) then {
|
||||
@ -27,4 +24,4 @@ _q1 set[0, (_q2 select 0) * _d - (_q2 select 2) * (_u select 0)];
|
||||
_q1 set[1, (_q2 select 1)];
|
||||
_q1 set[2, (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d];
|
||||
|
||||
[_p, _p1, _p2, _q1, _q2, _u, _d]
|
||||
[_p, _p1, _p2, _q1, _q2, _u, _d]
|
||||
|
@ -1,92 +1,116 @@
|
||||
/*
|
||||
* Author: Nou
|
||||
* Turn a laser designator on.
|
||||
* Searches for a laser spot given a seekers params.
|
||||
* Provides the interface for Missile Guidance
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Position of seeker (ASL) <position>
|
||||
* 1: Direction vector (will be normalized) <vector>
|
||||
* 2: Seeker FOV in degrees <number>
|
||||
* 3: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. <array>
|
||||
* 4: Seeker laser code. <number>
|
||||
* 0: Position of seeker (ASL) <ARRAY>
|
||||
* 1: Direction vector (will be normalized) <ARRAY>
|
||||
* 2: Seeker FOV in degrees <NUMBER>
|
||||
* 3: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. <ARRAY>
|
||||
* 4: Seeker laser code. <NUMBER>
|
||||
* 5: Ignore 1 (e.g. Player's vehicle) <OPTIONAL><OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Array, [Strongest compatible laser spot ASL pos, owner object] Nil array values if nothing found.
|
||||
*
|
||||
* Example:
|
||||
* [getPosASL player, [0,1,0], 90, [1500, 1500], 1111, player] call ace_laser_fnc_seekerFindLaserSpot;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
// #define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_pos", "_seekerWavelengths", "_seekerCode", "_spots", "_buckets", "_excludes", "_bucketIndex", "_finalPos", "_owner", "_obj", "_x", "_method"];
|
||||
private ["_emitterWavelength", "_laserCode", "_divergence", "_laser", "_res", "_bucketPos", "_bucketList", "_c", "_forEachIndex", "_index"];
|
||||
private ["_testPos", "_finalBuckets", "_largest", "_largestIndex", "_finalBucket", "_owners", "_avgX", "_avgY", "_avgZ", "_count", "_maxOwner", "_maxOwnerIndex", "_finalOwner"];
|
||||
private ["_dir", "_seekerCos", "_seekerFov", "_testDotProduct", "_testPoint", "_testPointVector"];
|
||||
BEGIN_COUNTER(seekerFindLaserSpot);
|
||||
|
||||
_pos = _this select 0;
|
||||
_dir = vectorNormalized (_this select 1);
|
||||
_seekerFov = _this select 2;
|
||||
_seekerWavelengths = _this select 3;
|
||||
_seekerCode = _this select 4;
|
||||
params ["_posASL", "_dir", "_seekerFov", "_seekerWavelengths", "_seekerCode", ["_ignoreObj1", objNull]];
|
||||
|
||||
_dir = vectorNormalized _dir;
|
||||
_seekerWavelengths params ["_seekerWavelengthMin", "_seekerWavelengthMax"];
|
||||
private _seekerCos = cos _seekerFov;
|
||||
|
||||
_seekerCos = cos _seekerFov;
|
||||
TRACE_5("",_posASL,_dir,_seekerFov,_seekerWavelengths,_seekerCode);
|
||||
|
||||
_spots = [];
|
||||
_buckets = [];
|
||||
_excludes = [];
|
||||
_bucketIndex = 0;
|
||||
_finalPos = nil;
|
||||
_finalOwner = nil;
|
||||
private _spots = [];
|
||||
private _finalPos = nil;
|
||||
private _finalOwner = objNull;
|
||||
|
||||
// Go through all lasers in GVAR(laserEmitters)
|
||||
{
|
||||
_obj = _x select 0;
|
||||
_owner = _x select 1;
|
||||
_method = _x select 2;
|
||||
_emitterWavelength = _x select 3;
|
||||
_laserCode = _x select 4;
|
||||
_divergence = _x select 5;
|
||||
if(alive _obj && {_emitterWavelength >= (_seekerWavelengths select 0)} && {_emitterWavelength <= (_seekerWavelengths select 1)} && {_laserCode == _seekerCode}) then {
|
||||
_laser = [];
|
||||
if(IS_CODE(_method)) then {
|
||||
_laser = _x call _method;
|
||||
_x params ["_obj", "_owner", "_laserMethod", "_emitterWavelength", "_laserCode", "_divergence"];
|
||||
TRACE_6("laser",_obj,_owner,_laserMethod,_emitterWavelength,_laserCode,_divergence);
|
||||
|
||||
if (alive _obj && {_emitterWavelength >= _seekerWavelengthMin} && {_emitterWavelength <= _seekerWavelengthMax} && {_laserCode == _seekerCode}) then {
|
||||
|
||||
private _laser = [];
|
||||
// Find laser pos and dir of the laser depending on type
|
||||
if (IS_STRING(_laserMethod)) then {
|
||||
_laser = _x call (missionNamespace getVariable [_laserMethod, []]);
|
||||
} else {
|
||||
if(IS_STRING(_method)) then {
|
||||
_laser = _x call (missionNamespace getVariable [_method, {}]);
|
||||
if (IS_CODE(_laserMethod)) then {
|
||||
_laser = _x call _laserMethod;
|
||||
} else {
|
||||
if(IS_ARRAY(_method)) then {
|
||||
if(count _method == 2) then {
|
||||
_laser = [ATLtoASL (_obj modelToWorldVisual (_method select 0)), _obj weaponDirection (_method select 1)];
|
||||
|
||||
if (IS_ARRAY(_laserMethod)) then {
|
||||
if (count _laserMethod == 2) then { // [modelPosition, weaponName] for _obj
|
||||
_laser = [AGLtoASL (_obj modelToWorldVisual (_laserMethod select 0)), _obj weaponDirection (_laserMethod select 1)];
|
||||
} else {
|
||||
if(count _method == 3) then {
|
||||
_laser = [ATLtoASL (_obj modelToWorldVisual (_method select 0)), (ATLtoASL (_obj modelToWorldVisual (_method select 1))) vectorFromTo (ATLtoASL (_obj modelToWorldVisual (_method select 2)))];
|
||||
if (count _laserMethod == 3) then {
|
||||
_laser = [AGLtoASL (_obj modelToWorldVisual (_laserMethod select 0)), (AGLtoASL (_obj modelToWorldVisual (_laserMethod select 1))) vectorFromTo (AGLtoASL (_obj modelToWorldVisual (_laserMethod select 2)))];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
//Handle Weird Data Return
|
||||
if (_laser params [["_laserPos", [], [[]], 3], ["_laserDir", [], [[]], 3]]) then {
|
||||
_res = [_laserPos, _laserDir, _divergence] call FUNC(shootCone);
|
||||
TRACE_1("",_laser);
|
||||
//Handle Weird Data Return - skips over this laser in the for loop
|
||||
if ((_laser isEqualTo []) || {_laser isEqualTo [-1, -1]}) exitWith {WARNING_1("Bad Laser Return",_laser);};
|
||||
_laser params [["_laserPos", [], [[]], 3], ["_laserDir", [], [[]], 3]];
|
||||
|
||||
if (GVAR(dispersionCount) > 0) then {
|
||||
// Shoot a cone with dispersion
|
||||
([_laserPos, _laserDir, _divergence, GVAR(dispersionCount), _obj] call FUNC(shootCone)) params ["", "", "_resultPositions"];
|
||||
{
|
||||
_testPoint = _x select 0;
|
||||
_testPointVector = vectorNormalized (_testPoint vectorDiff _pos);
|
||||
_testDotProduct = _dir vectorDotProduct _testPointVector;
|
||||
if(_testDotProduct > _seekerCos) then {
|
||||
private _testPointVector = _posASL vectorFromTo _testPoint;
|
||||
private _testDotProduct = _dir vectorDotProduct _testPointVector;
|
||||
if (_testDotProduct > _seekerCos) then {
|
||||
_spots pushBack [_testPoint, _owner];
|
||||
};
|
||||
} forEach (_res select 2);
|
||||
} forEach _resultPositions;
|
||||
} else {
|
||||
// Shoot a single perfect ray from source to target (note, increased chance to "miss" on weird objects like bushes / rocks)
|
||||
([_laserPos, _laserDir, _obj] call FUNC(shootRay)) params ["_resultPos", "_distance"];
|
||||
TRACE_2("spot",_resultPos,_distance);
|
||||
if (_distance > 0) then {
|
||||
private _testPointVector = _posASL vectorFromTo _resultPos;
|
||||
private _testDotProduct = _dir vectorDotProduct _testPointVector;
|
||||
if (_testDotProduct > _seekerCos) then {
|
||||
_spots pushBack [_resultPos, _owner];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} forEach (GVAR(laserEmitters) select 2);
|
||||
} forEach (GVAR(laserEmitters) select 2); // Go through all values in hash
|
||||
|
||||
if((count _spots) > 0) then {
|
||||
_bucketPos = nil;
|
||||
_bucketList = nil;
|
||||
_c = 0;
|
||||
TRACE_2("",count _spots, _spots);
|
||||
|
||||
if ((count _spots) > 0) then {
|
||||
private _bucketList = nil;
|
||||
private _bucketPos = nil;
|
||||
private _c = 0;
|
||||
private _buckets = [];
|
||||
private _excludes = [];
|
||||
private _bucketIndex = 0;
|
||||
|
||||
// Put close points together into buckets
|
||||
while { count(_spots) != count(_excludes) && _c < (count _spots) } do {
|
||||
scopeName "mainSearch";
|
||||
{
|
||||
if(!(_forEachIndex in _excludes)) then {
|
||||
_index = _buckets pushBack [_x, [_x]];
|
||||
if (!(_forEachIndex in _excludes)) then {
|
||||
private _index = _buckets pushBack [_x, [_x]];
|
||||
_excludes pushBack _forEachIndex;
|
||||
_bucketPos = _x select 0;
|
||||
_bucketList = (_buckets select _index) select 1;
|
||||
@ -94,9 +118,9 @@ if((count _spots) > 0) then {
|
||||
};
|
||||
} forEach _spots;
|
||||
{
|
||||
if(!(_forEachIndex in _excludes)) then {
|
||||
_testPos = (_x select 0);
|
||||
if(_testPos vectorDistanceSqr _bucketPos <= 100) then {
|
||||
if (!(_forEachIndex in _excludes)) then {
|
||||
private _testPos = (_x select 0);
|
||||
if ((_testPos vectorDistanceSqr _bucketPos) <= 100) then {
|
||||
_bucketList pushBack _x;
|
||||
_excludes pushBack _forEachIndex;
|
||||
};
|
||||
@ -104,55 +128,71 @@ if((count _spots) > 0) then {
|
||||
} forEach _spots;
|
||||
_c = _c + 1;
|
||||
};
|
||||
_finalBuckets = [];
|
||||
_largest = -1;
|
||||
_largestIndex = 0;
|
||||
|
||||
TRACE_1("",_buckets);
|
||||
|
||||
private _finalBuckets = [];
|
||||
private _largest = -1;
|
||||
private _largestIndex = 0;
|
||||
{
|
||||
_index = _finalBuckets pushBack [];
|
||||
// find bucket with largest number of points we can see
|
||||
private _index = _finalBuckets pushBack [];
|
||||
_bucketList = _finalBuckets select _index;
|
||||
{
|
||||
_testPos = (_x select 0);
|
||||
if(!terrainIntersectASL [_pos, _testPos] && {!lineIntersects [_pos, _testPos]}) then {
|
||||
private _testPos = (_x select 0) vectorAdd [0,0,0.05];
|
||||
private _testIntersections = lineIntersectsSurfaces [_posASL, _testPos, _ignoreObj1];
|
||||
if ([] isEqualTo _testIntersections) then {
|
||||
_bucketList pushBack _x;
|
||||
};
|
||||
} forEach (_x select 1);
|
||||
if((count _bucketList) > _largest) then {
|
||||
if ((count _bucketList) > _largest) then {
|
||||
_largest = (count _bucketList);
|
||||
_largestIndex = _index;
|
||||
};
|
||||
} forEach _buckets;
|
||||
|
||||
_finalBucket = _finalBuckets select _largestIndex;
|
||||
_owners = [] call CBA_fnc_hashCreate;
|
||||
private _finalBucket = _finalBuckets select _largestIndex;
|
||||
private _ownersHash = [] call CBA_fnc_hashCreate;
|
||||
|
||||
if(count _finalBucket > 0) then {
|
||||
_avgX = 0;
|
||||
_avgY = 0;
|
||||
_avgZ = 0;
|
||||
TRACE_2("",_finalBucket,_finalBuckets);
|
||||
|
||||
if (count _finalBucket > 0) then {
|
||||
// merge all points in the best bucket into an average point and find effective owner
|
||||
_finalPos = [0,0,0];
|
||||
{
|
||||
//player sideChat format["x: %1", _x];
|
||||
_avgX = _avgX + ((_x select 0) select 0);
|
||||
_avgY = _avgY + ((_x select 0) select 1);
|
||||
_avgZ = _avgZ + ((_x select 0) select 2);
|
||||
_owner = _x select 1;
|
||||
if ([_owners, _owner] call CBA_fnc_hashHasKey) then {
|
||||
private _count = [_owners, _owner] call CBA_fnc_hashGet;
|
||||
[_owners, _owner, _count + 1] call CBA_fnc_hashSet;
|
||||
_x params ["_xPos", "_owner"];
|
||||
_finalPos = _finalPos vectorAdd _xPos;
|
||||
if ([_ownersHash, _owner] call CBA_fnc_hashHasKey) then {
|
||||
private _count = [_ownersHash, _owner] call CBA_fnc_hashGet;
|
||||
[_ownersHash, _owner, _count + 1] call CBA_fnc_hashSet;
|
||||
} else {
|
||||
[_owners, _owner, 1] call CBA_fnc_hashSet;
|
||||
[_ownersHash, _owner, 1] call CBA_fnc_hashSet;
|
||||
};
|
||||
} forEach _finalBucket;
|
||||
_count = count _finalBucket;
|
||||
_finalPos = [_avgX/_count, _avgY/_count, _avgZ/_count];
|
||||
_maxOwner = -1;
|
||||
_maxOwnerIndex = 0;
|
||||
{
|
||||
if((_owners select 1) select _forEachIndex > _maxOwner) then {
|
||||
_maxOwner = (_owners select 1) select _forEachIndex;
|
||||
_maxOwnerIndex = _forEachIndex;
|
||||
|
||||
_finalPos = _finalPos vectorMultiply (1 / (count _finalBucket));
|
||||
|
||||
private _maxOwnerCount = -1;
|
||||
|
||||
[_ownersHash, {
|
||||
if (_value > _maxOwnerCount) then {
|
||||
_finalOwner = _key;
|
||||
};
|
||||
} forEach (_owners select 0);
|
||||
_finalOwner = (_owners select 0) select _maxOwnerIndex;
|
||||
}] call CBA_fnc_hashEachPair;
|
||||
};
|
||||
};
|
||||
[_finalPos, _owner];
|
||||
|
||||
END_COUNTER(seekerFindLaserSpot);
|
||||
|
||||
#ifdef DRAW_LASER_INFO
|
||||
if (isNil "_finalPos") then {
|
||||
drawIcon3D ["\A3\ui_f\data\map\vehicleicons\iconMan_ca.paa", [0.9,1,0,1], (ASLtoAGL _posASL), 1, 1, 0, format ["Seeker: %1", _code], 0.5, 0.025, "TahomaB"];
|
||||
} else {
|
||||
drawIcon3D ["\A3\ui_f\data\map\vehicleicons\iconManAT_ca.paa", [0.5,1,0,1], (ASLtoAGL _posASL), 1, 1, 0, format ["Seeker: %1", _code], 0.5, 0.025, "TahomaB"];
|
||||
drawLine3D [ASLtoAGL _posASL, ASLtoAGL _finalPos, [0.5,1,0,1]];
|
||||
};
|
||||
#endif
|
||||
|
||||
TRACE_2("return",_finalPos,_finalOwner);
|
||||
if (isNil "_finalPos") exitWith {[nil, _finalOwner]};
|
||||
[_finalPos, _finalOwner];
|
||||
|
@ -1,68 +1,71 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: Nou
|
||||
* Shoots multiple rays in a dispersion pattern
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Origin position ASL <ARRAY>
|
||||
* 1: Direction (normalized) <ARRAY>
|
||||
* 2: Divergence (mils) <OPTIONAL><NUMBER>
|
||||
* 3: Count at each divergence level <OPTIONAL><NUMBER>
|
||||
* 4: Ignore vehicle 1 (e.g. Player's vehicle) <OPTIONAL><OBJECT>
|
||||
*
|
||||
* Return value:
|
||||
* <ARRAY> [_longestReturn, _shortestReturn, _resultPositions]
|
||||
*
|
||||
* Example:
|
||||
* [getPosASL player, [0,1,0]] call ace_laser_fnc_shootCone;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
//#define DEBUG_MODE_FULL
|
||||
private ["_i", "_divergence","_pos","_vec","_longestReturn","_shortestReturn","_resultPositions","_p1","_p2","_p","_v","_cp","_vecRotateMap","_result", "_resultPos","_distance","_count","_pos2","_radOffset","_offset","_offsetPos","_offsetVector"];
|
||||
_divergence = 0.3;
|
||||
_pos = _this select 0;
|
||||
_vec = _this select 1;
|
||||
if(count _this > 2) then {
|
||||
_divergence = _this select 2;
|
||||
};
|
||||
_count = 3;
|
||||
if(count _this > 3) then {
|
||||
_count = _this select 3;
|
||||
};
|
||||
_longestReturn = -1000000000;
|
||||
_shortestReturn = 1000000000;
|
||||
_resultPositions = [];
|
||||
_p1 = [0,0,0];
|
||||
_p2 = +_vec;
|
||||
_p = (_vec call CBA_fnc_vect2polar);
|
||||
_v = [(_p select 0), (_p select 1), (_p select 2)+90] call CBA_fnc_polar2vect;
|
||||
_cp = _vec vectorCrossProduct _v;
|
||||
#include "script_component.hpp"
|
||||
|
||||
_vecRotateMap = [_cp, _p1, _p2] call FUNC(rotateVectLineGetMap);
|
||||
BEGIN_COUNTER(shootCone);
|
||||
|
||||
_result = [_pos, _vec] call FUNC(shootRay);
|
||||
_resultPos = _result select 0;
|
||||
if(!isNil "_resultPos") then {
|
||||
_distance = _result select 1;
|
||||
if(_distance < _shortestReturn) then {
|
||||
_shortestReturn = _distance;
|
||||
};
|
||||
if(_distance > _longestReturn) then {
|
||||
_longestReturn = _distance;
|
||||
};
|
||||
params ["_pos", "_vec", ["_divergence", 0.3], ["_count", 3], ["_ignoreObj1", objNull]];
|
||||
|
||||
private _longestReturn = -1000000000;
|
||||
private _shortestReturn = 1000000000;
|
||||
private _resultPositions = [];
|
||||
private _p1 = [0,0,0];
|
||||
private _p2 = +_vec;
|
||||
private _p = (_vec call CBA_fnc_vect2polar);
|
||||
private _v = [(_p select 0), (_p select 1), (_p select 2)+90] call CBA_fnc_polar2vect;
|
||||
private _cp = _vec vectorCrossProduct _v;
|
||||
|
||||
private _vecRotateMap = [_cp, _p1, _p2] call FUNC(rotateVectLineGetMap);
|
||||
|
||||
// Check first with a perfect ray to the center
|
||||
private _result = [_pos, _vec, _ignoreObj1] call FUNC(shootRay);
|
||||
private _resultPos = _result select 0;
|
||||
|
||||
if (!isNil "_resultPos") then {
|
||||
private _distance = _result select 1;
|
||||
if (_distance < _shortestReturn) then { _shortestReturn = _distance; };
|
||||
if (_distance > _longestReturn) then { _longestReturn = _distance; };
|
||||
_resultPositions pushBack _result;
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
// DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]];
|
||||
drawLine3D [ASLtoATL _pos, ASLtoATL _resultPos, [1,0,0,1]];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
_pos2 = _pos vectorAdd (_vec vectorMultiply 1000);
|
||||
private _pos2 = _pos vectorAdd (_vec vectorMultiply 1000);
|
||||
// Try at 3 radius (full, half, quarter of specified divergence)
|
||||
{
|
||||
for "_i" from 0 to ceil(_count*_x) do {
|
||||
_radOffset = random 360;
|
||||
_offset = [_vecRotateMap, (((360/_count)*_i)+_radOffset) mod 360] call FUNC(rotateVectLine);
|
||||
_offsetPos = _pos2 vectorAdd (_offset vectorMultiply (_divergence*_x));
|
||||
_offsetVector = _pos vectorFromTo _offsetPos;
|
||||
_result = [_pos, _offsetVector] call FUNC(shootRay);
|
||||
private _radOffset = random 360;
|
||||
for "_i" from 1 to ceil(_count*_x) do { // Will always do at least 1
|
||||
private _offset = [_vecRotateMap, (((360/_count)*_i)+_radOffset) mod 360] call FUNC(rotateVectLine);
|
||||
private _offsetPos = _pos2 vectorAdd (_offset vectorMultiply (_divergence*_x));
|
||||
|
||||
private _offsetVector = _pos vectorFromTo _offsetPos;
|
||||
_result = [_pos, _offsetVector, _ignoreObj1] call FUNC(shootRay);
|
||||
_resultPos = _result select 0;
|
||||
if(!isNil "_resultPos") then {
|
||||
_distance = _result select 1;
|
||||
if(_distance < _shortestReturn) then {
|
||||
_shortestReturn = _distance;
|
||||
};
|
||||
if(_distance > _longestReturn) then {
|
||||
_longestReturn = _distance;
|
||||
};
|
||||
if (!isNil "_resultPos") then {
|
||||
private _distance = _result select 1;
|
||||
if (_distance < _shortestReturn) then { _shortestReturn = _distance; };
|
||||
if (_distance > _longestReturn) then { _longestReturn = _distance; };
|
||||
_resultPositions pushBack _result;
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
// DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]];
|
||||
drawLine3D [ASLtoATL _pos, ASLtoATL _resultPos, [1,0,0,1]];
|
||||
#endif
|
||||
};
|
||||
};
|
||||
} forEach [1,0.5,0.25];
|
||||
[_longestReturn, _shortestReturn, _resultPositions];
|
||||
|
||||
END_COUNTER(shootCone);
|
||||
|
||||
[_longestReturn, _shortestReturn, _resultPositions];
|
||||
|
@ -1,24 +1,50 @@
|
||||
/*
|
||||
* Author: Nou, PabstMirror
|
||||
* Shoots a ray from a source to a direction and finds first intersction and distance
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Origin position ASL <ARRAY>
|
||||
* 1: Direction (normalized) <ARRAY>
|
||||
* 2: Ignore 1 (e.g. Player's vehicle) <OPTIONAL><OBJECT>
|
||||
* 2: Ignore 2 (e.g. Player's vehicle) <OPTIONAL><OBJECT>
|
||||
*
|
||||
* Return value:
|
||||
* <ARRAY> [posASL, distance] - pos will be nil if no intersection
|
||||
*
|
||||
* Example:
|
||||
* [getPosASL player, [0,1,0], player] call ace_laser_fnc_shootRay;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_pos", "_vec", "_distance", "_resultPos", "_fidelity", "_lastPos", "_i", "_nextPos"];
|
||||
scopeName "main";
|
||||
_pos = _this select 0;
|
||||
_vec = _this select 1;
|
||||
_distance = 0;
|
||||
_resultPos = nil;
|
||||
_fidelity = [1000,100,10,1,0.1];
|
||||
_lastPos = +_pos;
|
||||
{
|
||||
scopeName "mainSearch";
|
||||
for "_i" from 1 to 10 do {
|
||||
_nextPos = _lastPos vectorAdd (_vec vectorMultiply _x);
|
||||
if(terrainIntersectASL [_lastPos, _nextPos] || {lineIntersects [_lastPos, _nextPos]}) then {
|
||||
_resultPos = _lastPos;
|
||||
breakTo "mainSearch";
|
||||
} else {
|
||||
_distance = _distance + _x;
|
||||
_lastPos = _nextPos;
|
||||
};
|
||||
};
|
||||
} forEach _fidelity;
|
||||
[_resultPos, _distance];
|
||||
BEGIN_COUNTER(shootRay);
|
||||
|
||||
params ["_posASL", "_dir", ["_ignoreVehicle1", objNull], ["_ignoreVehicle2", objNull]];
|
||||
// TRACE_2("ray origin:", _posASL, _dir);
|
||||
|
||||
private _distance = 0;
|
||||
private _resultPos = nil;
|
||||
|
||||
private _farPoint = _posASL vectorAdd (_dir vectorMultiply 10000);
|
||||
private _intersects = lineIntersectsSurfaces [_posASL, _farPoint, _ignoreVehicle1, _ignoreVehicle2];
|
||||
|
||||
if (!(_intersects isEqualTo [])) then {
|
||||
(_intersects select 0) params ["_intersectPosASL", "", "_intersectObject"];
|
||||
// Move back slightly to prevents issues with it going below terrain
|
||||
_distance = (_posASL vectorDistance _intersectPosASL) - 0.005;
|
||||
_resultPos = _posASL vectorAdd (_dir vectorMultiply _distance);
|
||||
};
|
||||
|
||||
TRACE_3("", _resultPos, _distance, _intersects);
|
||||
|
||||
#ifdef DRAW_LASER_INFO
|
||||
if !(isNil "_resultPos") then {
|
||||
private _text = [_distance, 4, 0] call CBA_fnc_formatNumber;
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0, 1, 0, 1], ASLtoAGL _resultPos, 0.5, 0.5, 0, _text, 0.4, 0.025, "TahomaB"];
|
||||
drawLine3D [ASLtoAGL _posASL, ASLtoAGL _resultPos, [0,1,0,1]];
|
||||
};
|
||||
#endif
|
||||
|
||||
END_COUNTER(shootRay);
|
||||
[_resultPos, _distance];
|
||||
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Checks if the turret occupied by the given unit can lock a laser designator and select laser code.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Has designator? <BOOL>
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
EXPLODE_1_PVT(_this,_unit);
|
||||
|
||||
// Get the player turret path
|
||||
private ["_turret","_config","_turretConfig"];
|
||||
_turret = [_unit] call EFUNC(common,getTurretIndex);
|
||||
_config = configFile >> "CfgVehicles" >> typeOf vehicle _unit;
|
||||
_turretConfig = [_config, _turret] call EFUNC(common,getTurretConfigPath);
|
||||
|
||||
getNumber (_turretConfig >> QGVAR(CanLockLaser)) > 0
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Handler function for laser network code.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Emitter
|
||||
* 1: Owner
|
||||
*
|
||||
* Return Value:
|
||||
* [position, direction]
|
||||
*/
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_emmiter", "_owner", "_gunnerInfo", "_turretInfo", "_povPos", "_povDir"];
|
||||
|
||||
_emmiter = _this select 0;
|
||||
_owner = _this select 1;
|
||||
|
||||
// Not in a vehicle....
|
||||
// @TODO: handle lasering from turrets
|
||||
if( (vehicle _emmiter) == _emmiter && alive _emmiter && (currentWeapon _emmiter) == "LaserDesignator") exitWith {
|
||||
[(eyePos _emmiter), (eyeDirection _emmiter)]
|
||||
};
|
||||
|
||||
[-1,-1]
|
@ -1,27 +1,16 @@
|
||||
|
||||
|
||||
["ACE3 Equipment", QGVAR(LaserCodeUp), localize LSTRING(laserCodeUp),
|
||||
{
|
||||
if( EGVAR(laser_selfdesignate,active)
|
||||
||
|
||||
{ (currentWeapon ACE_player) == "Laserdesignator" && (call CBA_fnc_getFoV) select 1 > 5 } // If laserdesignator & FOV, we are in scope.
|
||||
||
|
||||
{ [ACE_player] call FUNC(unitTurretCanLockLaser) }
|
||||
) then {
|
||||
[] call FUNC(keyLaserCodeUp);
|
||||
};
|
||||
[1] call FUNC(keyLaserCodeChange);
|
||||
},
|
||||
{false},
|
||||
[16, [false, true, true]], false, 0] call CBA_fnc_addKeybind; // (ALT+CTRL+Q)
|
||||
|
||||
["ACE3 Equipment", QGVAR(LaserCodeDown), localize LSTRING(laserCodeDown),
|
||||
{
|
||||
if( EGVAR(laser_selfdesignate,active)
|
||||
||
|
||||
{ (currentWeapon ACE_player) == "Laserdesignator" && (call CBA_fnc_getFoV) select 1 > 5 } // If laserdesignator & FOV, we are in scope.
|
||||
||
|
||||
{ [ACE_player] call FUNC(unitTurretCanLockLaser) }
|
||||
) then {
|
||||
[] call FUNC(keyLaserCodeDown);
|
||||
};
|
||||
|
||||
[-1] call FUNC(keyLaserCodeChange);
|
||||
},
|
||||
{false},
|
||||
[18, [false, true, true]], false, 0] call CBA_fnc_addKeybind; // (ALT+CTRL+E)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define COMPONENT_BEAUTIFIED Laser
|
||||
#include "\z\ace\addons\main\script_mod.hpp"
|
||||
|
||||
// #define DRAW_LASER_INFO
|
||||
// #define DEBUG_MODE_FULL
|
||||
// #define DISABLE_COMPILE_CACHE
|
||||
// #define ENABLE_PERFORMANCE_COUNTERS
|
||||
@ -17,9 +18,6 @@
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
||||
|
||||
|
||||
#define FIREMODE_DIRECT_LOAL 1
|
||||
|
||||
|
||||
#define __LaserDesignatorIGUI (uiNamespace getVariable ["ACE_RscOptics_LaserDesignator", nil])
|
||||
#define __LaserDesignatorIGUI_LaserCode (__LaserDesignatorIGUI displayCtrl 123001)
|
||||
#define __LaserDesignatorIGUI_ACE_Distance (__LaserDesignatorIGUI displayCtrl 123002)
|
||||
|
@ -1,6 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project name="ACE">
|
||||
<Package name="Laser">
|
||||
<Key ID="STR_ACE_Laser_dispersionCount_displayName">
|
||||
<English>Laser Dispersion Simulation Count</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Laser_laserCode">
|
||||
<English>Laser Code</English>
|
||||
<German>Lasercode</German>
|
||||
|
@ -1 +0,0 @@
|
||||
z\ace\addons\laser_selfdesignate
|
@ -1,26 +0,0 @@
|
||||
|
||||
class Extended_PreStart_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_preStart));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_PreInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_pre_init));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_PostInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_post_init));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_Init_EventHandlers {
|
||||
class Helicopter {
|
||||
class ADDON {
|
||||
init = QUOTE(_this call DFUNC(initDesignatorActions));
|
||||
};
|
||||
};
|
||||
};
|
@ -1,49 +0,0 @@
|
||||
class CfgVehicles {
|
||||
class AllVehicles;
|
||||
class Air: AllVehicles {
|
||||
class Turrets;
|
||||
};
|
||||
|
||||
class Helicopter: Air {
|
||||
class Turrets {
|
||||
class MainTurret;
|
||||
};
|
||||
};
|
||||
|
||||
class Helicopter_Base_F: Helicopter {};
|
||||
|
||||
class Heli_Attack_01_base_F: Helicopter_Base_F {};
|
||||
|
||||
class B_Heli_Attack_01_F: Heli_Attack_01_base_F {
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {
|
||||
GVAR(Enabled) = 0; // Enable laser self-designation
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class Plane: Air {};
|
||||
class Plane_Base_F: Plane {
|
||||
class Turrets {
|
||||
class CopilotTurret;
|
||||
};
|
||||
};
|
||||
|
||||
/* @TODO: LGB GBU
|
||||
class Plane_CAS_01_base_F: Plane_Base_F {
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {
|
||||
GVAR(Enabled) = 1; // Enable laser self-designation
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class Plane_CAS_02_base_F: Plane_Base_F {
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {
|
||||
GVAR(Enabled) = 1; // Enable laser self-designation
|
||||
};
|
||||
};
|
||||
};
|
||||
*/
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
class CfgWeapons {
|
||||
// Disable locking unless newb mode
|
||||
class LauncherCore;
|
||||
class RocketPods: LauncherCore {
|
||||
// canLock = 1;
|
||||
};
|
||||
|
||||
class missiles_DAGR: RocketPods {
|
||||
//canLock = 1;
|
||||
};
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
ace_laser_selfdesignate
|
||||
=======================
|
||||
|
||||
Allows gunners to lase their own targets.
|
||||
|
||||
|
||||
## Maintainers
|
||||
|
||||
The people responsible for merging changes to this component or answering potential questions.
|
||||
|
||||
- [walterpearce](https://github.com/walterpearce)
|
||||
- [NouberNou](https://github.com/NouberNou)
|
@ -1,7 +0,0 @@
|
||||
|
||||
PREP(initDesignatorActions);
|
||||
PREP(laserHudDesignateOn);
|
||||
PREP(laserHudDesignateOff);
|
||||
PREP(unitTurretHasDesignator);
|
||||
|
||||
PREP(findLaserSource);
|
@ -1,2 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
@ -1,3 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
#include "XEH_PREP.hpp"
|
@ -1,11 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
ADDON = false;
|
||||
|
||||
#include "XEH_PREP.hpp"
|
||||
|
||||
GVAR(active) = false;
|
||||
|
||||
FUNC(getPosASL) = {visiblePositionASL (_this select 0)};
|
||||
|
||||
ADDON = true;
|
@ -1,18 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
class CfgPatches {
|
||||
class ADDON {
|
||||
name = COMPONENT_NAME;
|
||||
units[] = {};
|
||||
weapons[] = {};
|
||||
requiredVersion = REQUIRED_VERSION;
|
||||
requiredAddons[] = {"ace_laser"};
|
||||
author = ECSTRING(common,ACETeam);
|
||||
url = ECSTRING(main,URL);
|
||||
VERSION_CONFIG;
|
||||
};
|
||||
};
|
||||
|
||||
#include "CfgEventhandlers.hpp"
|
||||
#include "CfgWeapons.hpp"
|
||||
#include "CfgVehicles.hpp"
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Handler function for laser network code.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Emitter <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* 0: position <ARRAY>
|
||||
* 1: direction <ARRAY>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_gunnerInfo", "_turretInfo"];
|
||||
params ["_emmiter"];
|
||||
|
||||
_gunnerInfo = [_emmiter, (currentWeapon _emmiter)] call CBA_fnc_getFirer;
|
||||
_turretInfo = [_emmiter, _gunnerInfo select 1] call EFUNC(common,getTurretDirection);
|
||||
_turretInfo params [["_povPos", -1], ["_povDir", -1]];
|
||||
|
||||
[_povPos, _povDir]
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Author: esteldunedain
|
||||
* Initializes the actions for turning on/off the laser for vehicles that have them
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_vehicle"];
|
||||
|
||||
// Add action to class if it is not already done
|
||||
private ["_type", "_initializedClasses"];
|
||||
_type = typeOf _vehicle;
|
||||
_initializedClasses = GETGVAR(initializedClasses,[]);
|
||||
|
||||
// do nothing if the class is already initialized
|
||||
if (_type in _initializedClasses) exitWith {};
|
||||
_initializedClasses pushBack _type;
|
||||
GVAR(initializedClasses) = _initializedClasses;
|
||||
|
||||
{
|
||||
private ["_turretConfig","_onAction","_offAction"];
|
||||
_turretConfig = [configFile >> "CfgVehicles" >> _type, _x] call EFUNC(common,getTurretConfigPath);
|
||||
|
||||
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(active), _x], false];
|
||||
|
||||
// Add actions
|
||||
_onAction = [QGVAR(LaserOn), localize LSTRING(DesignatorOn), "",
|
||||
{
|
||||
// Statement
|
||||
_this call FUNC(laserHudDesignateOn)
|
||||
},
|
||||
{
|
||||
// Condition
|
||||
!GVAR(active) && {[ACE_player] call FUNC(unitTurretHasDesignator)}
|
||||
}] call EFUNC(interact_menu,createAction);
|
||||
|
||||
_offAction = [QGVAR(LaserOff), localize LSTRING(DesignatorOff), "",
|
||||
{
|
||||
// Statement
|
||||
_this call FUNC(laserHudDesignateOff)
|
||||
},
|
||||
{
|
||||
// Condition
|
||||
GVAR(active) && {[ACE_player] call FUNC(unitTurretHasDesignator)}
|
||||
}] call EFUNC(interact_menu,createAction);
|
||||
|
||||
[_type, 1, ["ACE_SelfActions"], _onAction] call EFUNC(interact_menu,addActionToClass);
|
||||
[_type, 1, ["ACE_SelfActions"], _offAction] call EFUNC(interact_menu,addActionToClass);
|
||||
};
|
||||
} forEach allTurrets _vehicle;
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Turns off passed laser self designation.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Shooter, player shooting the laser
|
||||
* 1: LaserUUID, the UUID of the laser returned by EFUNC(laser,laserOn)
|
||||
* 2: Local laser target, unused.
|
||||
*
|
||||
* Return Value:
|
||||
* True <BOOL>
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if( (count _this) > 2) then {
|
||||
params ["", "_laserUuid"];
|
||||
[_laserUuid] call EFUNC(laser,laserOff);
|
||||
// @TODO: Nou gets to field all tickets about missing lasers.
|
||||
//deleteVehicle _localLaserTarget;
|
||||
};
|
||||
|
||||
GVAR(active) = false;
|
||||
|
||||
if(!isNil QGVAR(selfDesignateHandle)) then {
|
||||
[GVAR(selfDesignateHandle)] call CBA_fnc_removePerFrameHandler;
|
||||
GVAR(selfDesignateHandle) = nil;
|
||||
};
|
||||
|
||||
true
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Turns on laser self designation from this vehicle based on the turret.
|
||||
* There are no arguments, because it is all strictly based on the users vehicle.
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
TRACE_1("enter", _this);
|
||||
|
||||
#define FCS_UPDATE_DELAY 1
|
||||
|
||||
FUNC(laserHudDesignatePFH) = {
|
||||
private ["_strongestResultPos", "_args", "_localLaserTarget", "_laserResultPosition", "_laserResult", "_shooter", "_vehicle", "_weapon", "_gunnerInfo", "_turretInfo", "_pov", "_gunBeg", "_gunEnd", "_povPos", "_povDir", "_result", "_resultPositions", "_firstResult", "_forceUpdateTime"];
|
||||
params ["_args"];
|
||||
_args params ["_shooter", "_localLaserTarget"];
|
||||
_vehicle = vehicle _shooter;
|
||||
TRACE_1("", _args);
|
||||
|
||||
if((vehicle _shooter) == _shooter || {!alive _shooter} || {isNull _vehicle} || {!GVAR(active)} ) exitWith {
|
||||
_args call FUNC(laserHudDesignateOff);
|
||||
};
|
||||
if(!([_shooter] call FUNC(unitTurretHasDesignator)) ) exitWith {
|
||||
_args call FUNC(laserHudDesignateOff);
|
||||
};
|
||||
|
||||
if( (count _args) < 4) then {
|
||||
_args set[3, diag_tickTime + FCS_UPDATE_DELAY];
|
||||
};
|
||||
_forceUpdateTime = _args select 3;
|
||||
|
||||
// @TODO: We don't have anything here we need to do the calculations for right now
|
||||
/*
|
||||
|
||||
_gunnerInfo = [_vehicle, (currentWeapon _vehicle)] call CBA_fnc_getFirer;
|
||||
_turretInfo = [_vehicle, _gunnerInfo select 1] call EFUNC(common,getTurretDirection);
|
||||
_povPos = _turretInfo select 0;
|
||||
|
||||
_laserCode = (vehicle ACE_player) getVariable["ace_laser_code", ACE_DEFAULT_LASER_CODE];
|
||||
_waveLength = (vehicle ACE_player) getVariable["ace_laser_waveLength", ACE_DEFAULT_LASER_WAVELENGTH];
|
||||
|
||||
|
||||
_laserResult = [_povPos, [_waveLength,_waveLength], _laserCode] call EFUNC(laser,seekerFindLaserSpot);
|
||||
_laserResultPosition = _laserResult select 0;
|
||||
TRACE_1("Search", _laserResult);
|
||||
|
||||
if((count _laserResult) > 0) then {
|
||||
// @TODO: Nou gets to field all tickets about missing lasers.
|
||||
//_localLaserTarget setPosASL _laserResultPosition;
|
||||
};
|
||||
*/
|
||||
|
||||
if(diag_tickTime > _forceUpdateTime) then {
|
||||
["ace_fcs_forceUpdate", []] call ace_common_fnc_localEvent;
|
||||
_args set[3, diag_tickTime + FCS_UPDATE_DELAY];
|
||||
};
|
||||
|
||||
_this set[0, _args];
|
||||
};
|
||||
|
||||
private ["_laserTarget", "_handle", "_vehicle", "_laserUuid", "_waveLength", "_beamSpread", "_laserCode"];
|
||||
|
||||
if(!GVAR(active)) then {
|
||||
GVAR(active) = true;
|
||||
|
||||
TRACE_1("Activating laser", "");
|
||||
|
||||
// Get the self-designation variables, or use defaults
|
||||
_laserCode = (vehicle ACE_player) getVariable["ace_laser_code", ACE_DEFAULT_LASER_CODE];
|
||||
_waveLength = (vehicle ACE_player) getVariable["ace_laser_waveLength", ACE_DEFAULT_LASER_WAVELENGTH];
|
||||
_beamSpread = (vehicle ACE_player) getVariable["ace_laser_beamSpread", ACE_DEFAULT_LASER_BEAMSPREAD];
|
||||
|
||||
_laserUuid = [(vehicle ACE_player), ACE_player, QFUNC(findLaserSource), _waveLength, _laserCode, _beamSpread] call EFUNC(laser,laserOn);
|
||||
|
||||
// @TODO: Create the local target for the players side
|
||||
// @TODO: Nou gets to field all tickets about missing lasers.
|
||||
//_localLaserTarget = "LaserTargetW" createVehicleLocal (getpos ACE_player);
|
||||
|
||||
GVAR(selfDesignateHandle) = [FUNC(laserHudDesignatePFH), 0.1, [ACE_player, _laserUuid, nil]] call CBA_fnc_addPerFrameHandler;
|
||||
} else {
|
||||
[] call FUNC(laserHudDesignateOff);
|
||||
[] call FUNC(laserHudDesignateOn);
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Author: esteldunedain
|
||||
* Checks if the turret occupied by the given unit has a laser designator
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Has unit designator <BOOL>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
// Get the player turret path
|
||||
private ["_turret","_config","_turretConfig"];
|
||||
_turret = [_unit] call EFUNC(common,getTurretIndex);
|
||||
_config = configFile >> "CfgVehicles" >> typeOf vehicle _unit;
|
||||
_turretConfig = [_config, _turret] call EFUNC(common,getTurretConfigPath);
|
||||
|
||||
getNumber (_turretConfig >> QGVAR(Enabled)) > 0
|
@ -1 +0,0 @@
|
||||
#include "\z\ace\addons\laser_selfdesignate\script_component.hpp"
|
@ -1,17 +0,0 @@
|
||||
#define COMPONENT laser_selfdesignate
|
||||
#define COMPONENT_BEAUTIFIED Laser Selfdesignate
|
||||
#include "\z\ace\addons\main\script_mod.hpp"
|
||||
|
||||
// #define DEBUG_MODE_FULL
|
||||
// #define DISABLE_COMPILE_CACHE
|
||||
// #define ENABLE_PERFORMANCE_COUNTERS
|
||||
|
||||
#ifdef DEBUG_ENABLED_LASER_SELFDESIGNATE
|
||||
#define DEBUG_MODE_FULL
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_SETTINGS_LASER_SELFDESIGNATE
|
||||
#define DEBUG_SETTINGS DEBUG_SETTINGS_LASER_SELFDESIGNATE
|
||||
#endif
|
||||
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project name="ACE">
|
||||
<Package name="Laser_SelfDesignate">
|
||||
<Key ID="STR_ACE_Laser_SelfDesignate_DesignatorOn">
|
||||
<English>Laser Designator On</English>
|
||||
<German>Lasermarkierer an</German>
|
||||
<Spanish>Designador láser encendido</Spanish>
|
||||
<Russian>ЛЦУ ВКЛ</Russian>
|
||||
<Czech>Laserový značkovač zapnut</Czech>
|
||||
<Polish>Desygnator laserowy wł.</Polish>
|
||||
<French>Désignateur laser allumé</French>
|
||||
<Hungarian>Lézeres Megjelölő Be</Hungarian>
|
||||
<Italian>Designatore laser acceso</Italian>
|
||||
<Portuguese>Designador Laser Ligado</Portuguese>
|
||||
<Japanese>レーザー指示を起動</Japanese>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Laser_SelfDesignate_DesignatorOff">
|
||||
<English>Laser Designator Off</English>
|
||||
<German>Lasermarkierer aus</German>
|
||||
<Spanish>Designador láser apagado</Spanish>
|
||||
<Russian>ЛЦУ ВЫКЛ</Russian>
|
||||
<Czech>Laserový značkovat vypnut</Czech>
|
||||
<Polish>Desygnator laserowy wył.</Polish>
|
||||
<French>Désignateur laser éteint</French>
|
||||
<Hungarian>Lézeres Megjelölő Ki</Hungarian>
|
||||
<Italian>Designatore laser spento</Italian>
|
||||
<Portuguese>Designador Laser Desligado</Portuguese>
|
||||
<Japanese>レーザー指示を停止</Japanese>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
@ -16,13 +16,17 @@ GVAR(nearUnits) = [];
|
||||
|
||||
// @todo. Maybe move to common?
|
||||
[{
|
||||
// handle RHS / bugged vehicle slots
|
||||
private _camPosAGL = positionCameraToWorld [0,0,0];
|
||||
if !((_camPosAGL select 0) isEqualType 0) exitWith {};
|
||||
|
||||
private _nearUnits = [];
|
||||
{
|
||||
_nearUnits append crew _x;
|
||||
if (count _nearUnits > 10) exitWith {
|
||||
_nearUnits resize 10;
|
||||
};
|
||||
} forEach nearestObjects [positionCameraToWorld [0,0,0], ["AllVehicles"], 50]; // when moving this, search also for units inside vehicles. currently breaks the laser in FFV
|
||||
} forEach nearestObjects [_camPosAGL, ["AllVehicles"], 50]; // when moving this, search also for units inside vehicles. currently breaks the laser in FFV
|
||||
|
||||
GVAR(nearUnits) = _nearUnits;
|
||||
|
||||
|
@ -7,4 +7,11 @@ class ACE_Settings {
|
||||
description = CSTRING(rotateModifierKey_description);
|
||||
values[] = {"$STR_A3_OPTIONS_DISABLED", "ALT", "CTRL", "SHIFT"};
|
||||
};
|
||||
class GVAR(drawStaightLines) {
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
isClientSettable = 1;
|
||||
displayName = CSTRING(drawStaightLines_displayName);
|
||||
description = CSTRING(drawStaightLines_description);
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
PREP(calculateMapScale);
|
||||
PREP(canUseMapGPS);
|
||||
PREP(canUseMapTools);
|
||||
PREP(drawLinesOnRoamer);
|
||||
PREP(handleMouseButton);
|
||||
PREP(handleMouseMove);
|
||||
PREP(isInsideMapTool);
|
||||
|
@ -30,5 +30,13 @@ GVAR(mapTool_isRotating) = false;
|
||||
} else {
|
||||
// Hide GPS
|
||||
[false] call FUNC(openMapGps);
|
||||
|
||||
// Handle closing map in middle of line drawing (it's never created)
|
||||
GVAR(freedrawing) = false;
|
||||
};
|
||||
}] call CBA_fnc_addPlayerEventHandler;
|
||||
|
||||
|
||||
GVAR(freeDrawingData) = [];
|
||||
GVAR(freedrawing) = false;
|
||||
|
||||
|
144
addons/maptools/functions/fnc_drawLinesOnRoamer.sqf
Normal file
144
addons/maptools/functions/fnc_drawLinesOnRoamer.sqf
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Prevents the cursor from entering the roamer when drawing lines and records the positions
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Map <CONTROL>
|
||||
* 1: Roamer Width <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* Nothing
|
||||
*
|
||||
* Example:
|
||||
* [map, 300] call ace_maptools_fnc_drawLinesOnRoamer
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if (!GVAR(drawStaightLines)) exitWith {};
|
||||
|
||||
params ["_theMap", "_roamerWidth"];
|
||||
GVAR(mapTool_pos) params ["_roamerPosX", "_roamerPosY"];
|
||||
|
||||
private _posCenter = [_roamerPosX, _roamerPosY, 0];
|
||||
|
||||
private _posTopRight = [
|
||||
_roamerPosX + (cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth,
|
||||
_roamerPosY + (-sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth,
|
||||
0];
|
||||
|
||||
private _posTopLeft = [
|
||||
_roamerPosX + (-cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth,
|
||||
_roamerPosY + (sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth,
|
||||
0];
|
||||
|
||||
private _posBottomLeft = [
|
||||
_roamerPosX + (-cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth,
|
||||
_roamerPosY + (sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth,
|
||||
0];
|
||||
|
||||
private _posBottomRight = [
|
||||
_roamerPosX + (cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth,
|
||||
_roamerPosY + (-sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth,
|
||||
0];
|
||||
|
||||
private _fnc_Distance = { // Get distance point _p is from a line made from _a to _b (uses 3d array commands, but z should be 0)
|
||||
// Ref: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Vector_formulation
|
||||
params ["_a", "_b", "_p"];
|
||||
private _n = _b vectorDiff _a;
|
||||
private _pa = _a vectorDiff _p;
|
||||
private _c = _n vectorMultiply ((_pa vectorDotProduct _n) / (_n vectorDotProduct _n));
|
||||
private _d = _pa vectorDiff _c;
|
||||
sqrt (_d vectorDotProduct _d);
|
||||
};
|
||||
|
||||
private _currentMousePos = _theMap ctrlMapScreenToWorld getMousePosition;
|
||||
_currentMousePos set [2, 0];
|
||||
|
||||
// Break the roamer rectangle into 4 triangle, one for each side
|
||||
switch (true) do {
|
||||
case (_currentMousePos inPolygon [_posCenter, _posTopLeft, _posBottomLeft]): { // Left
|
||||
private _distanceToRoamerLine = ([_posTopLeft, _posBottomLeft, _currentMousePos] call _fnc_Distance);
|
||||
_currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) - 90) ,0] call CBA_fnc_polar2vect);
|
||||
if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line
|
||||
GVAR(freeDrawingData) = ["left", _currentMousePos, _currentMousePos];
|
||||
} else {
|
||||
if ((GVAR(freeDrawingData) select 0) == "left") then { // We are already drawing on this line, find best spot
|
||||
if ((_currentMousePos distance2d _posTopLeft) < ((GVAR(freeDrawingData) select 1) distance2d _posTopLeft)) then {
|
||||
GVAR(freeDrawingData) set [1, _currentMousePos];
|
||||
};
|
||||
if ((_currentMousePos distance2d _posBottomLeft) < ((GVAR(freeDrawingData) select 2) distance2d _posBottomLeft)) then {
|
||||
GVAR(freeDrawingData) set [2, _currentMousePos];
|
||||
};
|
||||
};
|
||||
};
|
||||
private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos;
|
||||
setMousePosition _screenPosOfCorrectedPos;
|
||||
};
|
||||
case (_currentMousePos inPolygon [_posCenter, _posTopLeft, _posTopRight]): { // Top
|
||||
private _distanceToRoamerLine = ([_posTopLeft, _posTopRight, _currentMousePos] call _fnc_Distance);
|
||||
_currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) + 0) ,0] call CBA_fnc_polar2vect);
|
||||
if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line
|
||||
GVAR(freeDrawingData) = ["top", _currentMousePos, _currentMousePos];
|
||||
} else {
|
||||
if ((GVAR(freeDrawingData) select 0) == "top") then { // We are already drawing on this line, find best spot
|
||||
if ((_currentMousePos distance2d _posTopLeft) < ((GVAR(freeDrawingData) select 1) distance2d _posTopLeft)) then {
|
||||
GVAR(freeDrawingData) set [1, _currentMousePos];
|
||||
};
|
||||
if ((_currentMousePos distance2d _posTopRight) < ((GVAR(freeDrawingData) select 2) distance2d _posTopRight)) then {
|
||||
GVAR(freeDrawingData) set [2, _currentMousePos];
|
||||
};
|
||||
};
|
||||
};
|
||||
private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos;
|
||||
setMousePosition _screenPosOfCorrectedPos;
|
||||
};
|
||||
case (_currentMousePos inPolygon [_posCenter, _posTopRight, _posBottomRight]): { // Right
|
||||
private _distanceToRoamerLine = ([_posTopRight, _posBottomRight, _currentMousePos] call _fnc_Distance);
|
||||
_currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) + 90) ,0] call CBA_fnc_polar2vect);
|
||||
if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line
|
||||
GVAR(freeDrawingData) = ["right", _currentMousePos, _currentMousePos];
|
||||
} else {
|
||||
if ((GVAR(freeDrawingData) select 0) == "right") then { // We are already drawing on this line, find best spot
|
||||
if ((_currentMousePos distance2d _posTopRight) < ((GVAR(freeDrawingData) select 1) distance2d _posTopRight)) then {
|
||||
GVAR(freeDrawingData) set [1, _currentMousePos];
|
||||
};
|
||||
if ((_currentMousePos distance2d _posBottomRight) < ((GVAR(freeDrawingData) select 2) distance2d _posBottomRight)) then {
|
||||
GVAR(freeDrawingData) set [2, _currentMousePos];
|
||||
};
|
||||
};
|
||||
};
|
||||
private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos;
|
||||
setMousePosition _screenPosOfCorrectedPos;
|
||||
};
|
||||
case (_currentMousePos inPolygon [_posCenter, _posBottomLeft, _posBottomRight]): { // Bottom
|
||||
private _distanceToRoamerLine = ([_posBottomLeft, _posBottomRight, _currentMousePos] call _fnc_Distance);
|
||||
_currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) + 180) ,0] call CBA_fnc_polar2vect);
|
||||
if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line
|
||||
GVAR(freeDrawingData) = ["bottom", _currentMousePos, _currentMousePos];
|
||||
} else {
|
||||
if ((GVAR(freeDrawingData) select 0) == "bottom") then { // We are already drawing on this line, find best spot
|
||||
if ((_currentMousePos distance2d _posBottomLeft) < ((GVAR(freeDrawingData) select 1) distance2d _posBottomLeft)) then {
|
||||
GVAR(freeDrawingData) set [1, _currentMousePos];
|
||||
};
|
||||
if ((_currentMousePos distance2d _posBottomRight) < ((GVAR(freeDrawingData) select 2) distance2d _posBottomRight)) then {
|
||||
GVAR(freeDrawingData) set [2, _currentMousePos];
|
||||
};
|
||||
};
|
||||
};
|
||||
private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos;
|
||||
setMousePosition _screenPosOfCorrectedPos;
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posTopRight,24,24,getDir player,'1,1',1,0.03,'TahomaB','right'];
|
||||
_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posTopLeft,24,24,getDir player,'-1,1',1,0.03,'TahomaB','right'];
|
||||
_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posBottomLeft,24,24,getDir player,'-1,-1',1,0.03,'TahomaB','right'];
|
||||
_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posBottomRight,24,24,getDir player,'1,-1',1,0.03,'TahomaB','right'];
|
||||
if !(GVAR(freeDrawingData) isEqualTo []) then {
|
||||
_theMap drawIcon ['iconStaticMG',[0,0,1,1],GVAR(freeDrawingData) select 1,24,24,getDir player,'1,-1',1,0.03,'TahomaB','right'];
|
||||
_theMap drawIcon ['iconStaticMG',[0,0,1,1],GVAR(freeDrawingData) select 2,24,24,getDir player,'1,-1',1,0.03,'TahomaB','right'];
|
||||
};
|
||||
#endif
|
@ -15,6 +15,51 @@ params ["_dir", "_params"];
|
||||
_params params ["_control", "_button", "_screenPosX", "_screenPosY", "_shiftKey", "_ctrlKey", "_altKey"];
|
||||
TRACE_2("params",_dir,_params);
|
||||
|
||||
// Using line drawing
|
||||
if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith {
|
||||
if (GVAR(freedrawing) && {_dir == 0}) then {
|
||||
GVAR(freedrawing) = false;
|
||||
GVAR(drawPosEnd) = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
|
||||
TRACE_1("Ending Line",GVAR(freedrawing),GVAR(drawPosEnd));
|
||||
[{
|
||||
if (allMapMarkers isEqualTo []) exitWith {};
|
||||
private _markerName = allMapMarkers select (count allMapMarkers - 1);
|
||||
private _markerPos = getMarkerPos _markerName;
|
||||
private _distanceCheck = _markerPos distance2d GVAR(drawPosStart);
|
||||
|
||||
TRACE_3("Line Drawn",_markerName,_markerPos,_distanceCheck);
|
||||
|
||||
if (_distanceCheck > 1) exitWith {WARNING("Wrong Marker!");};
|
||||
if ((count GVAR(freeDrawingData)) != 3) exitWith {TRACE_1("never touched roamer",GVAR(freeDrawingData));};
|
||||
|
||||
GVAR(freeDrawingData) params ["", "_startStraightPos", "_endStraightPos"];
|
||||
_startStraightPos set [2, 0];
|
||||
_endStraightPos set [2, 0];
|
||||
|
||||
// Convert marker to rectangle and change it's pos/size/dir
|
||||
_markerName setMarkerShape "RECTANGLE";
|
||||
|
||||
private _difPos = _endStraightPos vectorDiff _startStraightPos;
|
||||
private _mag = vectorMagnitude _difPos;
|
||||
_markerName setMarkerPos (_startStraightPos vectorAdd (_difPos vectorMultiply 0.5));
|
||||
_markerName setMarkerSize [10, _mag / 2];
|
||||
_markerName setMarkerDir (_difPos call CBA_fnc_vectDir);
|
||||
|
||||
}, []] call CBA_fnc_execNextFrame;
|
||||
} else {
|
||||
if (_ctrlKey && {_dir == 1}) then {
|
||||
GVAR(freeDrawingData) = [];
|
||||
GVAR(freedrawing) = true;
|
||||
GVAR(drawPosStart) = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
|
||||
TRACE_2("Starting Line",GVAR(freedrawing),GVAR(drawPosStart));
|
||||
} else {
|
||||
GVAR(freedrawing) = false;
|
||||
TRACE_1("weird - reseting",GVAR(freedrawing));
|
||||
};
|
||||
};
|
||||
false
|
||||
};
|
||||
|
||||
private _handled = false;
|
||||
|
||||
// If it's not a left button event, exit
|
||||
|
@ -11,11 +11,6 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
#define TEXTURE_WIDTH_IN_M 6205
|
||||
#define DIST_BOTTOM_TO_CENTER_PERC -0.33
|
||||
#define DIST_TOP_TO_CENTER_PERC 0.65
|
||||
#define DIST_LEFT_TO_CENTER_PERC 0.30
|
||||
|
||||
if (GVAR(mapTool_Shown) == 0) exitWith {false};
|
||||
private _textureWidth = [TEXTURE_WIDTH_IN_M, TEXTURE_WIDTH_IN_M / 2] select (GVAR(mapTool_Shown) - 1);
|
||||
|
||||
|
@ -12,10 +12,6 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
#define TEXTURE_WIDTH_IN_M 6205
|
||||
#define CENTER_OFFSET_Y_PERC 0.1606
|
||||
#define CONSTANT_SCALE 0.2
|
||||
|
||||
params ["_theMap"];
|
||||
|
||||
if ((GVAR(mapTool_Shown) == 0) || {!("ACE_MapTools" in items ACE_player)}) exitWith {};
|
||||
@ -30,6 +26,8 @@ if (GVAR(mapTool_Shown) == 1) then {
|
||||
_textureWidth = TEXTURE_WIDTH_IN_M / 2;
|
||||
};
|
||||
|
||||
if (GVAR(freedrawing)) then {[_theMap, _textureWidth] call FUNC(drawLinesOnRoamer);};
|
||||
|
||||
// Update scale of both parts
|
||||
getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"];
|
||||
private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale));
|
||||
|
@ -15,3 +15,10 @@
|
||||
#endif
|
||||
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
||||
|
||||
#define TEXTURE_WIDTH_IN_M 6205
|
||||
#define CENTER_OFFSET_Y_PERC 0.1606
|
||||
#define CONSTANT_SCALE 0.2
|
||||
#define DIST_BOTTOM_TO_CENTER_PERC -0.33
|
||||
#define DIST_TOP_TO_CENTER_PERC 0.65
|
||||
#define DIST_LEFT_TO_CENTER_PERC 0.30
|
||||
|
@ -158,5 +158,11 @@
|
||||
<Japanese>マップ ツールを回転させるキーを編集できます。</Japanese>
|
||||
<Polish>Modyfikator pozwalający na obracanie narzędzi nawigacyjnych</Polish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_MapTools_drawStaightLines_displayName">
|
||||
<English>Draw straight lines with maptools</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_MapTools_drawStaightLines_description">
|
||||
<English>Draw on the edge of maptools to draw straight lines. Note: Must hover at midpoint to delete.</English>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
||||
|
@ -1,44 +1,7 @@
|
||||
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";
|
||||
|
||||
// Reenable this settings when ACE laser targeting and missile guidance is reenabled
|
||||
//laserLock = 1;
|
||||
//airLock = 0;
|
||||
//irLock = 0;
|
||||
//weaponLockSystem = "4 + 16";
|
||||
//fuseDistance = 2;
|
||||
//timeToLive = 60;
|
||||
// Turn off arma crosshair-guidance
|
||||
//manualControl = 0;
|
||||
// ACE uses these values
|
||||
//trackOversteer = 1;
|
||||
//trackLead = 0;
|
||||
|
||||
maxSpeed = 720;
|
||||
maxControlRange = 5000;
|
||||
maneuvrability = 8;
|
||||
|
||||
simulationStep = 0.01;
|
||||
airFriction = 0.1;
|
||||
sideAirFriction = 0.16;
|
||||
initTime = 0.002;
|
||||
thrustTime = 1.07;
|
||||
thrust = 530;
|
||||
|
||||
effectsMissileInit = "MissileDAR1";
|
||||
effectsMissile = "missile2";
|
||||
whistleDist = 4;
|
||||
muzzleEffect = "";
|
||||
};
|
||||
class M_PG_AT: MissileBase {};
|
||||
|
||||
class ACE_Hydra70_DAGR: M_PG_AT {
|
||||
displayName = CSTRING(Hydra70_DAGR);
|
||||
@ -47,13 +10,18 @@ class CfgAmmo {
|
||||
description = CSTRING(Hydra70_DAGR_Desc);
|
||||
descriptionShort = CSTRING(Hydra70_DAGR_Desc);
|
||||
|
||||
irLock = 0;
|
||||
laserLock = 0;
|
||||
manualControl = 0;
|
||||
maxSpeed = 300;
|
||||
|
||||
EGVAR(rearm,caliber) = 70;
|
||||
|
||||
class ADDON {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0.00025; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.001; // Maximum flap deflection for guidance
|
||||
minDeflection = 0.0005; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.0025; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
@ -1,24 +1,20 @@
|
||||
class CfgVehicles {
|
||||
|
||||
class AllVehicles;
|
||||
class Air: AllVehicles {
|
||||
class Air;
|
||||
class Helicopter: Air {
|
||||
class Turrets;
|
||||
};
|
||||
|
||||
class Helicopter: Air {
|
||||
class Turrets {
|
||||
class MainTurret;
|
||||
};
|
||||
};
|
||||
class Helicopter_Base_F: Helicopter {};
|
||||
class Heli_Attack_01_base_F: Helicopter_Base_F {};
|
||||
class B_Heli_Attack_01_F : Heli_Attack_01_base_F {
|
||||
class Helicopter_Base_F: Helicopter {
|
||||
class Turrets: Turrets {
|
||||
class MainTurret;
|
||||
};
|
||||
};
|
||||
|
||||
class ACE_Comanche_Test : B_Heli_Attack_01_F {
|
||||
class Heli_Attack_01_base_F: Helicopter_Base_F {
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {};
|
||||
};
|
||||
};
|
||||
class B_Heli_Attack_01_F: Heli_Attack_01_base_F {};
|
||||
class ACE_Comanche_Test : B_Heli_Attack_01_F { // Comanche testbed (Hidden: Scope=1)
|
||||
scope = 1;
|
||||
scopeCurator = 0;
|
||||
displayName = "ACE_Comanche_Test";
|
||||
@ -28,9 +24,9 @@ class CfgVehicles {
|
||||
};
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {
|
||||
magazines[] = {"ACE_500Rnd_20mm_shells_Comanche", "24Rnd_ACE_Hellfire_AGM114K"};
|
||||
weapons[] = {"gatling_20mm", "ace_missileguidance_dagr", "Laserdesignator_mounted"};
|
||||
magazines[] = {"ACE_500Rnd_20mm_shells_Comanche", "6Rnd_ACE_Hydra70_DAGR", "Laserbatteries"};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -1,12 +1,10 @@
|
||||
class Mode_SemiAuto;
|
||||
class CfgWeapons {
|
||||
class CannonCore;
|
||||
class LauncherCore;
|
||||
class missiles_DAGR;
|
||||
|
||||
class RocketPods: LauncherCore {
|
||||
// canLock = 1;
|
||||
};
|
||||
class missiles_DAGR : RocketPods {
|
||||
canLock = 2;
|
||||
class GVAR(dagr): missiles_DAGR {
|
||||
canLock = 0;
|
||||
magazines[] = {"6Rnd_ACE_Hydra70_DAGR","12Rnd_ACE_Hydra70_DAGR","24Rnd_ACE_Hydra70_DAGR"};
|
||||
lockingTargetSound[] = {"",0,1};
|
||||
lockedTargetSound[] = {"",0,1};
|
||||
};
|
||||
};
|
||||
|
@ -7,9 +7,9 @@
|
||||
#define STAGE_TERMINAL 4
|
||||
|
||||
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", "_state"];
|
||||
private ["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"];
|
||||
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
|
||||
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_state"];
|
||||
private["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"];
|
||||
_seekerTargetPos = _this select 0;
|
||||
_launchParams = _this select 1;
|
||||
|
||||
@ -37,19 +37,19 @@ switch( (_state select 0) ) do {
|
||||
case STAGE_LAUNCH: {
|
||||
TRACE_1("STAGE_LAUNCH","");
|
||||
if(_distanceToShooter < 10) then {
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget * 2];
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
||||
} else {
|
||||
_state set [0, STAGE_CLIMB];
|
||||
_state set[0, STAGE_CLIMB];
|
||||
};
|
||||
};
|
||||
case STAGE_CLIMB: {
|
||||
TRACE_1("STAGE_CLIMB","");
|
||||
_cruisAlt = 60 * (_distanceShooterToTarget/2000);
|
||||
|
||||
if( ((ASLToATL _projectilePos) select 2) - ((ASLToATL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||
_state set [0, STAGE_TERMINAL];
|
||||
if( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||
_state set[0, STAGE_TERMINAL];
|
||||
} else {
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget * 1.5];
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5];
|
||||
};
|
||||
};
|
||||
case STAGE_TERMINAL: {
|
||||
@ -59,7 +59,7 @@ switch( (_state select 0) ) do {
|
||||
};
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
drawLine3D [(ASLtoATL _returnTargetPos), (ASLtoATL _seekerTargetPos), [0, 1, 0, 1]];
|
||||
drawLine3D [(ASLtoAGL _returnTargetPos), (ASLtoAGL _seekerTargetPos), [0,1,0,1]];
|
||||
#endif
|
||||
|
||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
||||
|
@ -7,9 +7,9 @@
|
||||
#define STAGE_TERMINAL 4
|
||||
|
||||
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", "_state"];
|
||||
private ["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"];
|
||||
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
|
||||
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_state"];
|
||||
private["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"];
|
||||
|
||||
_seekerTargetPos = _this select 0;
|
||||
_launchParams = _this select 1;
|
||||
@ -38,7 +38,7 @@ switch( (_state select 0) ) do {
|
||||
case STAGE_LAUNCH: {
|
||||
TRACE_1("STAGE_LAUNCH","");
|
||||
if(_distanceToShooter < 10) then {
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget * 2];
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
||||
} else {
|
||||
_state set[0, STAGE_CLIMB];
|
||||
};
|
||||
@ -50,34 +50,34 @@ switch( (_state select 0) ) do {
|
||||
_cruisAlt = 140 * (_distanceShooterToTarget/1250);
|
||||
TRACE_1("_cruisAlt", _cruisAlt);
|
||||
};
|
||||
if(((ASLToATL _projectilePos) select 2) - ((ASLToATL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||
if( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||
if(_cruisAlt < 140) then {
|
||||
_state set[0, STAGE_TERMINAL];
|
||||
} else {
|
||||
_state set[0, STAGE_COAST];
|
||||
};
|
||||
} else {
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0, 0, _distanceToTarget * 1.5];
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5];
|
||||
};
|
||||
};
|
||||
case STAGE_COAST: {
|
||||
TRACE_1("STAGE_COAST","");
|
||||
TRACE_1("", ((ASLToATL _projectilePos) select 2) - (( ASLToATL _seekerTargetPos) select 2) );
|
||||
if(_distanceToTarget < (((ASLToATL _projectilePos) select 2) - (( ASLToATL _seekerTargetPos) select 2)) * 1.5) then {
|
||||
TRACE_1("", ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) );
|
||||
if(_distanceToTarget < ( ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ) * 1.5) then {
|
||||
_state set[0, STAGE_TERMINAL];
|
||||
} else {
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0, 0, (_projectilePos select 2)];
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,(_projectilePos select 2)];
|
||||
};
|
||||
};
|
||||
case STAGE_TERMINAL: {
|
||||
TRACE_1("STAGE_TERMINAL","");
|
||||
//_returnTargetPos = _seekerTargetPos vectorAdd [0, 0, _distanceToTarget * 0.02];
|
||||
//_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget * 0.02];
|
||||
_returnTargetPos = _seekerTargetPos;
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
drawLine3D [(ASLtoATL _returnTargetPos), (ASLtoATL _seekerTargetPos), [0, 1, 0, 1]];
|
||||
drawLine3D [(ASLtoAGL _returnTargetPos), (ASLtoAGL _seekerTargetPos), [0,1,0,1]];
|
||||
#endif
|
||||
|
||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
||||
|
@ -2,8 +2,8 @@
|
||||
#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", "_shooterPos"];
|
||||
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
|
||||
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_shooterPos"];
|
||||
_seekerTargetPos = _this select 0;
|
||||
_launchParams = _this select 1;
|
||||
|
||||
@ -13,7 +13,7 @@ _targetLaunchParams = _launchParams select 1;
|
||||
_shooterPos = getPosASL _shooter;
|
||||
_projectilePos = getPosASL _projectile;
|
||||
|
||||
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
||||
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
||||
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
||||
|
||||
TRACE_3("", _distanceToTarget, _distanceToShooter, _seekerTargetPos);
|
||||
@ -22,7 +22,7 @@ TRACE_3("", _distanceToTarget, _distanceToShooter, _seekerTargetPos);
|
||||
_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 {
|
||||
if( ((ASLtoAGL _projectilePos) select 2) < 5 && _distanceToShooter < 15) then {
|
||||
_addHeight = _addHeight vectorAdd [0,0,_distanceToTarget];
|
||||
} else {
|
||||
// If we are below the target, increase the climbing arc
|
||||
@ -43,8 +43,8 @@ if( (_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd _addHeight;
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
drawLine3D [(ASLtoATL _returnTargetPos) vectorAdd _addHeight, ASLtoATL _returnTargetPos, [0,1,0,1]];
|
||||
drawLine3D [(ASLtoAGL _returnTargetPos) vectorAdd _addHeight, ASLtoAGL _returnTargetPos, [0,1,0,1]];
|
||||
#endif
|
||||
|
||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
||||
_returnTargetPos;
|
||||
_returnTargetPos;
|
||||
|
@ -58,7 +58,7 @@ _adjustVector = _targetVector vectorDiff (vectorDir _projectile);
|
||||
|
||||
_yaw = 0;
|
||||
_pitch = 0;
|
||||
_roll = 0;
|
||||
_roll = 0;
|
||||
if((_adjustVector select 0) < 0) then {
|
||||
_yaw = - ( (_minDeflection max (abs(_adjustVector select 0) min _maxDeflection) ) );
|
||||
} else {
|
||||
@ -90,17 +90,17 @@ if(accTime > 0) then {
|
||||
};
|
||||
|
||||
#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]];
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoAGL _projectilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
|
||||
drawLine3D [ASLtoAGL _projectilePos, ASLtoAGL _profileAdjustedTargetPos, [1,0,0,1]];
|
||||
|
||||
_ps = "#particlesource" createVehicleLocal (ASLtoATL _projectilePos);
|
||||
_ps = "#particlesource" createVehicleLocal (ASLtoAGL _projectilePos);
|
||||
_PS setParticleParams [["\A3\Data_f\cl_basic", 8, 3, 1], "", "Billboard", 1, 3.0141, [0, 0, 2], [0, 0, 0], 1, 1.275, 1, 0, [1, 1], [[1, 0, 0, 1], [1, 0, 0, 1], [1, 0, 0, 1]], [1], 1, 0, "", "", nil];
|
||||
_PS setDropInterval 3.0;
|
||||
|
||||
hintSilent format["d: %1", _distanceToTarget];
|
||||
//hintSilent format["d: %1", _distanceToTarget];
|
||||
#endif
|
||||
|
||||
_stateParams set[0, diag_tickTime];
|
||||
|
||||
_args set[4, _stateParams];
|
||||
_this set[0, _args];
|
||||
_this set[0, _args];
|
||||
|
@ -1,32 +1,32 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
// #define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
||||
private ["_angleFov", "_canSeeTarget", "_foundTargetPos", "_laserResult", "_launchParams", "_seekerParams", "_laserCode", "_laserParams", "_seekerTargetPos", "_sensorPos", "_target"];
|
||||
_seekerTargetPos = _this select 0;
|
||||
_launchParams = _this select 1;
|
||||
_seekerParams = _launchParams select 3;
|
||||
_angleFov = _seekerParams select 0;
|
||||
params ["_lastSeekTargetPos", "_args"];
|
||||
_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
||||
_firedEH params ["_shooter","_weapon","_muzzle","_mode","_ammo","_magazine","_projectile"];
|
||||
_launchParams params ["","","","","","_laserParams"];
|
||||
_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"];
|
||||
_laserParams params ["_code", "_wavelengthMin", "_wavelengthMax"];
|
||||
|
||||
_laserParams = (_launchParams select 1) select 5;
|
||||
TRACE_2("", _launchParams, _laserParams);
|
||||
if(!isNil "_target") then {
|
||||
private "_foundTargetPos";
|
||||
|
||||
if (!isNil "_target") then {
|
||||
// Handle AI or moving vanilla lasers
|
||||
_foundTargetPos = getPosASL _target;
|
||||
} else {
|
||||
_laserResult = [(getPosASL _projectile), (velocity _projectile), _angleFov, [(_laserParams select 1),(_laserParams select 2)], (_laserParams select 0)] call EFUNC(laser,seekerFindLaserSpot);
|
||||
private _laserResult = [(getPosASL _projectile), (velocity _projectile), _seekerAngle, [_wavelengthMin, _wavelengthMax], _code, _projectile] call EFUNC(laser,seekerFindLaserSpot);
|
||||
_foundTargetPos = _laserResult select 0;
|
||||
TRACE_1("Search", _laserResult);
|
||||
};
|
||||
|
||||
if(!isNil "_foundTargetPos") then {
|
||||
//_canSeeTarget = [_projectile, _foundTargetPos, _angleFov] call FUNC(checkSeekerAngle);
|
||||
|
||||
// Fov is already checked by laser func, check if distance
|
||||
|
||||
private _canSeeTarget = _seekerMaxRange >= (_foundTargetPos vectorDistance (getPosASL _projectile));
|
||||
// If we got here, it was an invalid target, just return a spot 5m in front of the missile
|
||||
if(!_canSeeTarget) then {
|
||||
_foundTargetPos = _sensorPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
_foundTargetPos;
|
||||
_foundTargetPos;
|
||||
|
@ -46,8 +46,8 @@ if (_lastFireMode != -1) then {
|
||||
|
||||
[{
|
||||
private ["_chargeText", "_currentChargeMode", "_currentFireMode", "_display", "_elevDeg", "_elevationDiff", "_lookVector", "_notGunnerView", "_realAzimuth", "_realElevation", "_upVectorDir", "_useMils", "_weaponDir"];
|
||||
PARAMS_2(_args,_pfID);
|
||||
EXPLODE_2_PVT(_args,_mortarVeh,_fireModes);
|
||||
params ["_args", "_pfID"];
|
||||
_args params ["_mortarVeh", "_fireModes"];
|
||||
|
||||
if ((vehicle ACE_player) != _mortarVeh) then {
|
||||
[_pfID] call CBA_fnc_removePerFrameHandler;
|
||||
@ -80,7 +80,19 @@ if (_lastFireMode != -1) then {
|
||||
//(looking at the sky VS looking at ground will radicaly change fire direction because BIS)
|
||||
_realAzimuth = -1;
|
||||
_realElevation = -1;
|
||||
if ((ctrlText (_display displayCtrl 173)) == "--") then {
|
||||
|
||||
private _useRealWeaponDir = (ctrlText (_display displayCtrl 173)) == "--";
|
||||
if (_useRealWeaponDir && {(_mortarVeh ammo (currentWeapon _mortarVeh)) == 0}) then {
|
||||
// With no ammo, distance display will be empty, but gun will still fire at wonky angle if aimed at ground
|
||||
private _testSeekerPosASL = AGLtoASL (positionCameraToWorld [0,0,0]);
|
||||
private _testSeekerDir = _testSeekerPosASL vectorFromTo (AGLtoASL (positionCameraToWorld [0,0,1]));
|
||||
private _laserRange = [_testSeekerPosASL, _testSeekerDir, _mortarVeh] call EFUNC(laser,shootRay);
|
||||
_laserRange params ["", ["_rayDistance", -5]]; // ToDo: move shootRay to common
|
||||
TRACE_2("",_rayDistance,viewDistance);
|
||||
_useRealWeaponDir = _rayDistance > viewDistance; // If we are looking at infinity (based on viewDistance)
|
||||
};
|
||||
|
||||
if (_useRealWeaponDir) then {
|
||||
//No range (looking at sky), it will follow weaponDir:
|
||||
_weaponDir = _mortarVeh weaponDirection (currentWeapon _mortarVeh);
|
||||
_realAzimuth = (_weaponDir select 0) atan2 (_weaponDir select 1);
|
||||
|
@ -68,6 +68,8 @@ private _ambientBrightness = ((([] call EFUNC(common,ambientBrightness)) + ([0,
|
||||
private _maxDistance = _ambientBrightness * GVAR(PlayerNamesViewDistance);
|
||||
|
||||
private _camPosAGL = positionCameraToWorld [0, 0, 0];
|
||||
if !((_camPosAGL select 0) isEqualType 0) exitWith {}; // handle RHS / bugged vehicle slots
|
||||
|
||||
private _camPosASL = AGLtoASL _camPosAGL;
|
||||
private _vecy = (AGLtoASL positionCameraToWorld [0, 0, 1]) vectorDiff _camPosASL;
|
||||
|
||||
|
@ -377,9 +377,10 @@ class CfgVehicles {
|
||||
class HitBody {
|
||||
armor = 0.6;
|
||||
material = -1;
|
||||
name = "zbytek";
|
||||
name = "mat_rim";
|
||||
visual = "mat_rim";
|
||||
passThrough = 1;
|
||||
radius = 0.1;
|
||||
explosionShielding = 1;
|
||||
};
|
||||
};
|
||||
|
Binary file not shown.
Binary file not shown.
@ -6,15 +6,11 @@ class CfgSkeletons {
|
||||
};
|
||||
|
||||
class ace_wheel: Default {
|
||||
skeletonBones[] = {
|
||||
"zbytek", ""
|
||||
};
|
||||
skeletonBones[] = {};
|
||||
};
|
||||
|
||||
class ace_track: Default {
|
||||
skeletonBones[] = {
|
||||
"zbytek", ""
|
||||
};
|
||||
skeletonBones[] = {};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ GVAR(distanceIndex) = -1;
|
||||
[_this select 1] call CBA_fnc_removePerFrameHandler;
|
||||
};
|
||||
|
||||
_result = [eyePos ACE_player, ACE_player weaponDirection (currentWeapon ACE_player)] call EFUNC(laser,shootRay);
|
||||
_result = [eyePos ACE_player, ACE_player weaponDirection (currentWeapon ACE_player), ACE_player] call EFUNC(laser,shootRay);
|
||||
_distance = _result select 1;
|
||||
|
||||
_distance = _distance - 1 + (random 2);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user