mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Merge branch 'master' into csw-separate-settings
This commit is contained in:
commit
46ef4b1b1f
@ -11,5 +11,8 @@ trim_trailing_whitespace = true
|
|||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
[Makefile]
|
[Makefile]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -23,14 +23,14 @@ All good? Then proceed and fill out the items below.
|
|||||||
**Mods (complete and add to the following information):**
|
**Mods (complete and add to the following information):**
|
||||||
- **Arma 3:** `x.xx` [e.g. 1.00 stable, rc, dev]
|
- **Arma 3:** `x.xx` [e.g. 1.00 stable, rc, dev]
|
||||||
- **CBA:** `3.x.x` [e.g. 3.0.0 stable, commit hash]
|
- **CBA:** `3.x.x` [e.g. 3.0.0 stable, commit hash]
|
||||||
- **ACE3:** `3.x.x` [eg. 3.0.0 stable, commit hash]
|
- **ACE3:** `3.x.x` [e.g. 3.0.0 stable, commit hash]
|
||||||
<!-- Make sure to reproduce the issue with only CBA and ACE3 on a newly created mission! -->
|
<!-- Make sure to reproduce the issue with only CBA and ACE3 on a newly created mission! -->
|
||||||
|
|
||||||
**Description:**
|
**Description:**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**Steps to reproduce:**
|
**Steps to reproduce:**
|
||||||
_Follow [https://ace3.acemod.org/img/wiki/user/issue_flowchart.webp](this flowchart)!_
|
_Follow [this flowchart](https://ace3.acemod.org/img/wiki/user/issue_flowchart.webp)!_
|
||||||
|
|
||||||
1. _Go to ..._
|
1. _Go to ..._
|
||||||
2. _Click ..._
|
2. _Click ..._
|
||||||
|
9
.github/workflows/arma.yml
vendored
9
.github/workflows/arma.yml
vendored
@ -27,15 +27,6 @@ jobs:
|
|||||||
- name: Validate function headers
|
- name: Validate function headers
|
||||||
run: python3 docs/tools/document_functions.py --debug
|
run: python3 docs/tools/document_functions.py --debug
|
||||||
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout the source code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Lint (sqflint)
|
|
||||||
uses: arma-actions/sqflint@master
|
|
||||||
continue-on-error: true # No failure due to many false-positives
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
68
.github/workflows/extensions.yml
vendored
68
.github/workflows/extensions.yml
vendored
@ -1,29 +1,65 @@
|
|||||||
name: Extensions
|
name: Extensions
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- 'extensions/**'
|
- 'extension/**'
|
||||||
|
- 'Cargo.toml'
|
||||||
|
- 'Cargo.lock'
|
||||||
|
- '.github/workflows/extensions.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout the source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
rustup toolchain update stable --no-self-update
|
||||||
|
rustup default stable
|
||||||
|
rustup component add clippy rustfmt
|
||||||
|
- name: Run rustfmt
|
||||||
|
run: cargo fmt -- --check
|
||||||
|
- name: Run clippy
|
||||||
|
run: cargo clippy --all -- -Dwarnings
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: xd009642/tarpaulin
|
||||||
|
options: --security-opt seccomp=unconfined
|
||||||
|
steps:
|
||||||
|
- name: Checkout the source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- name: Test & Coverage
|
||||||
|
run: cargo tarpaulin --verbose --no-default-features --workspace --timeout 240
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest]
|
arrays: [
|
||||||
|
os: { tag: "windows-latest", target: "i686-pc-windows-msvc" },
|
||||||
|
os: { tag: "windows-latest", target: "x86_64-pc-windows-msvc" },
|
||||||
|
]
|
||||||
|
runs-on: ${{ matrix.arrays.os.tag }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the source code
|
- name: Checkout the source code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Build
|
- name: Install stable Rust
|
||||||
shell: cmd
|
uses: actions-rs/toolchain@v1
|
||||||
run: |
|
|
||||||
cd extensions
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. && cmake --build .
|
|
||||||
- name: Upload Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: ace3_extensions-${{ matrix.os }}-debug
|
target: ${{ matrix.arrays.os.target }}
|
||||||
path: extensions/build
|
toolchain: stable
|
||||||
|
default: true
|
||||||
|
- name: Rust Cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --verbose
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.arrays.os.target }}
|
||||||
|
path: target/debug/ace.dll
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 30
|
||||||
|
2
.github/workflows/hemtt.yml
vendored
2
.github/workflows/hemtt.yml
vendored
@ -33,6 +33,8 @@ jobs:
|
|||||||
xcopy /e /h /q pullrequest\addons addons\
|
xcopy /e /h /q pullrequest\addons addons\
|
||||||
xcopy /e /h /q pullrequest\optionals optionals\
|
xcopy /e /h /q pullrequest\optionals optionals\
|
||||||
xcopy /e /h /q pullrequest\include include\
|
xcopy /e /h /q pullrequest\include include\
|
||||||
|
xcopy /y /h /q pullrequest\ace.dll ace.dll
|
||||||
|
xcopy /y /h /q pullrequest\ace_x64.dll ace_x64.dll
|
||||||
- name: Run HEMTT build
|
- name: Run HEMTT build
|
||||||
run: hemtt build
|
run: hemtt build
|
||||||
- name: Rename build folder
|
- name: Rename build folder
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,8 +2,6 @@
|
|||||||
*.zip
|
*.zip
|
||||||
release/*
|
release/*
|
||||||
releases/*
|
releases/*
|
||||||
extensions/vcproj32/*
|
|
||||||
extensions/vcproj64/*
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
hemtt
|
hemtt
|
||||||
hemtt.exe
|
hemtt.exe
|
||||||
@ -20,4 +18,5 @@ CHANGELOG.md
|
|||||||
sqfvm.exe
|
sqfvm.exe
|
||||||
ArmaScriptCompiler.exe
|
ArmaScriptCompiler.exe
|
||||||
*.sqfc
|
*.sqfc
|
||||||
|
target/
|
||||||
!extras/**/*.zip
|
!extras/**/*.zip
|
||||||
|
@ -28,38 +28,32 @@ exclude = [
|
|||||||
"zeus/functions/fnc_zeusAttributes.sqf",
|
"zeus/functions/fnc_zeusAttributes.sqf",
|
||||||
]
|
]
|
||||||
|
|
||||||
[hemtt.launch]
|
[hemtt.launch.default]
|
||||||
workshop = [
|
workshop = [
|
||||||
"450814997", # CBA_A3
|
"450814997", # CBA_A3
|
||||||
]
|
]
|
||||||
|
|
||||||
[hemtt.launch.spe]
|
[hemtt.launch.spe]
|
||||||
workshop = [
|
extends = "default"
|
||||||
"450814997", # CBA_A3
|
|
||||||
]
|
|
||||||
dlc = [
|
dlc = [
|
||||||
"spe"
|
"spe"
|
||||||
]
|
]
|
||||||
|
|
||||||
[hemtt.launch.vn]
|
[hemtt.launch.vn]
|
||||||
workshop = [
|
extends = "default"
|
||||||
"450814997", # CBA_A3's Workshop ID
|
|
||||||
]
|
|
||||||
dlc = [
|
dlc = [
|
||||||
"S.O.G. Prairie Fire",
|
"S.O.G. Prairie Fire",
|
||||||
]
|
]
|
||||||
|
|
||||||
[hemtt.launch.ws]
|
[hemtt.launch.ws]
|
||||||
workshop = [
|
extends = "default"
|
||||||
"450814997", # CBA_A3's Workshop ID
|
|
||||||
]
|
|
||||||
dlc = [
|
dlc = [
|
||||||
"Western Sahara",
|
"Western Sahara",
|
||||||
]
|
]
|
||||||
|
|
||||||
[hemtt.launch.rhs]
|
[hemtt.launch.rhs]
|
||||||
|
extends = "default"
|
||||||
workshop = [
|
workshop = [
|
||||||
"450814997", # CBA_A3's Workshop ID
|
|
||||||
"843425103", # RHS AFRF Workshop ID
|
"843425103", # RHS AFRF Workshop ID
|
||||||
"843577117", # RHS USAF Workshop ID
|
"843577117", # RHS USAF Workshop ID
|
||||||
"843593391", # RHS GREF Workshop ID
|
"843593391", # RHS GREF Workshop ID
|
||||||
|
1364
Cargo.lock
generated
Normal file
1364
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [
|
||||||
|
"extension"
|
||||||
|
]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "z"
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
strip = true
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ace_fcs.dll
BIN
ace_fcs.dll
Binary file not shown.
BIN
ace_fcs_x64.dll
BIN
ace_fcs_x64.dll
Binary file not shown.
BIN
ace_x64.dll
Normal file
BIN
ace_x64.dll
Normal file
Binary file not shown.
@ -1,10 +1,10 @@
|
|||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
GVAR(currentbulletID) = -1;
|
#include "initKeybinds.inc.sqf"
|
||||||
|
|
||||||
GVAR(Protractor) = false;
|
GVAR(Protractor) = false;
|
||||||
GVAR(ProtractorStart) = CBA_missionTime;
|
GVAR(ProtractorStart) = CBA_missionTime;
|
||||||
GVAR(allBullets) = [];
|
GVAR(allBullets) = createHashMap;
|
||||||
GVAR(currentGrid) = 0;
|
GVAR(currentGrid) = 0;
|
||||||
|
|
||||||
if (!hasInterface) exitWith {};
|
if (!hasInterface) exitWith {};
|
||||||
@ -24,22 +24,6 @@ if (!hasInterface) exitWith {};
|
|||||||
|
|
||||||
// Register Perframe Handler
|
// Register Perframe Handler
|
||||||
[LINKFUNC(handleFirePFH), GVAR(simulationInterval)] call CBA_fnc_addPerFrameHandler;
|
[LINKFUNC(handleFirePFH), GVAR(simulationInterval)] call CBA_fnc_addPerFrameHandler;
|
||||||
|
|
||||||
//Add warnings for missing compat PBOs (only if AB is on)
|
|
||||||
{
|
|
||||||
_x params ["_modPBO", "_compatPBO"];
|
|
||||||
if ([_modPBO] call EFUNC(common,isModLoaded) && {!([_compatPBO] call EFUNC(common,isModLoaded))}) then {
|
|
||||||
WARNING_2("Weapon Mod [%1] missing ace compat pbo [%2] (from @ace\optionals)",_modPBO,_compatPBO);
|
|
||||||
};
|
|
||||||
} forEach [
|
|
||||||
["RH_acc","ace_compat_rh_acc"],
|
|
||||||
["RH_de_cfg","ace_compat_rh_de"],
|
|
||||||
["RH_m4_cfg","ace_compat_rh_m4"],
|
|
||||||
["RH_PDW","ace_compat_rh_pdw"],
|
|
||||||
["RKSL_PMII","ace_compat_rksl_pm_ii"],
|
|
||||||
["iansky_opt","ace_compat_sma3_iansky"],
|
|
||||||
["R3F_Armes","ace_compat_r3f"]
|
|
||||||
];
|
|
||||||
}] call CBA_fnc_addEventHandler;
|
}] call CBA_fnc_addEventHandler;
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
#ifdef DEBUG_MODE_FULL
|
||||||
|
@ -18,10 +18,3 @@ class CfgPatches {
|
|||||||
#include "CfgVehicles.hpp"
|
#include "CfgVehicles.hpp"
|
||||||
#include "RscTitles.hpp"
|
#include "RscTitles.hpp"
|
||||||
#include "ACE_Settings.hpp"
|
#include "ACE_Settings.hpp"
|
||||||
|
|
||||||
class ACE_Extensions {
|
|
||||||
class ace_advanced_ballistics {
|
|
||||||
windows = 1;
|
|
||||||
client = 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
@ -80,7 +80,7 @@ for "_i" from 0 to (count _cfgWeapons)-1 do {
|
|||||||
diag_log text format ["AB_Diagnose_barrelTwist,%1,%2,%3,%4,%5",_weapon,_magazine,_ammo,_twistDirection,_barrelTwist];
|
diag_log text format ["AB_Diagnose_barrelTwist,%1,%2,%3,%4,%5",_weapon,_magazine,_ammo,_twistDirection,_barrelTwist];
|
||||||
};
|
};
|
||||||
if (_barrelLength == 0) then {
|
if (_barrelLength == 0) then {
|
||||||
diag_log text format ["AB_Diagnose_barrelLength,%1,%2,%3,%4,%5",_weapon,_magazine,_ammo,_barrelLength];
|
diag_log text format ["AB_Diagnose_barrelLength,%1,%2,%3,%4",_weapon,_magazine,_ammo,_barrelLength];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} forEach _magazines;
|
} forEach _magazines;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: Glowbal, Ruthberg, joko // Jonas
|
* Author: Glowbal, Ruthberg, joko // Jonas, Brett Mayson
|
||||||
* Handle the PFH for Bullets
|
* Handle the PFH for Bullets
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
private _deleted = false;
|
private _deleted = false;
|
||||||
{
|
{
|
||||||
_x params ["_bullet","_caliber","_bulletTraceVisible","_index"];
|
_y params ["_bullet","_caliber","_bulletTraceVisible"];
|
||||||
|
|
||||||
if (alive _bullet) then {
|
if (alive _bullet) then {
|
||||||
private _bulletVelocity = velocity _bullet;
|
private _bulletVelocity = velocity _bullet;
|
||||||
@ -27,13 +27,21 @@ private _deleted = false;
|
|||||||
drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[0.02*_caliber,0.01*_caliber],[[0,0,0,0.65],[0,0,0,0.2]],[1,0],0,0,"","",""];
|
drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[0.02*_caliber,0.01*_caliber],[[0,0,0,0.65],[0,0,0,0.2]],[1,0],0,0,"","",""];
|
||||||
};
|
};
|
||||||
|
|
||||||
_bullet setVelocity (_bulletVelocity vectorAdd (parseSimpleArray ("ace_advanced_ballistics" callExtension format["simulate:%1:%2:%3:%4:%5:%6", _index, _bulletVelocity, _bulletPosition, wind, ASLToATL(_bulletPosition) select 2, CBA_missionTime toFixed 6])));
|
(
|
||||||
|
"ace" callExtension ["ballistics:bullet:simulate", [
|
||||||
|
_x,
|
||||||
|
_bulletVelocity,
|
||||||
|
_bulletPosition,
|
||||||
|
wind,
|
||||||
|
ASLToATL(_bulletPosition) select 2,
|
||||||
|
CBA_missionTime toFixed 6
|
||||||
|
]]
|
||||||
|
) params ["_data", "_code"];
|
||||||
|
if (_code == 0) then {
|
||||||
|
_bullet setVelocity (_bulletVelocity vectorAdd (parseSimpleArray (_data)));
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
GVAR(allBullets) set [_forEachIndex, objNull];
|
GVAR(allBullets) deleteAt _x;
|
||||||
_deleted = true;
|
"ace" callExtension ["ballistics:bullet:delete", [_x]];
|
||||||
};
|
};
|
||||||
} forEach GVAR(allBullets);
|
} forEach GVAR(allBullets)
|
||||||
|
|
||||||
if (_deleted) then {
|
|
||||||
GVAR(allBullets) = GVAR(allBullets) - [objNull];
|
|
||||||
};
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: Glowbal, Ruthberg
|
* Author: Glowbal, Ruthberg, Brett Mayson
|
||||||
*
|
*
|
||||||
* Handles advanced ballistics for (BulletBase) projectiles. Called from the unified fired EH only for players.
|
* Handles advanced ballistics for (BulletBase) projectiles. Called from the unified fired EH only for players.
|
||||||
*
|
*
|
||||||
@ -19,7 +19,7 @@
|
|||||||
//IGNORE_PRIVATE_WARNING ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle", "_gunner", "_turret"];
|
//IGNORE_PRIVATE_WARNING ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle", "_gunner", "_turret"];
|
||||||
TRACE_10("firedEH:",_unit,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile,_vehicle,_gunner,_turret);
|
TRACE_10("firedEH:",_unit,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile,_vehicle,_gunner,_turret);
|
||||||
|
|
||||||
if (!(_ammo isKindOf "BulletBase")) exitWith {};
|
if !(_ammo isKindOf "BulletBase") exitWith {};
|
||||||
if (!alive _projectile) exitWith {};
|
if (!alive _projectile) exitWith {};
|
||||||
if (underwater _unit) exitWith {};
|
if (underwater _unit) exitWith {};
|
||||||
|
|
||||||
@ -62,11 +62,11 @@ if (_abort) exitWith {};
|
|||||||
// Get Weapon and Ammo Configurations
|
// Get Weapon and Ammo Configurations
|
||||||
private _AmmoCacheEntry = uiNamespace getVariable format[QGVAR(%1), _ammo];
|
private _AmmoCacheEntry = uiNamespace getVariable format[QGVAR(%1), _ammo];
|
||||||
if (isNil "_AmmoCacheEntry") then {
|
if (isNil "_AmmoCacheEntry") then {
|
||||||
_AmmoCacheEntry = _ammo call FUNC(readAmmoDataFromConfig);
|
_AmmoCacheEntry = _ammo call FUNC(readAmmoDataFromConfig);
|
||||||
};
|
};
|
||||||
private _WeaponCacheEntry = uiNamespace getVariable format[QGVAR(%1), _weapon];
|
private _WeaponCacheEntry = uiNamespace getVariable format[QGVAR(%1), _weapon];
|
||||||
if (isNil "_WeaponCacheEntry") then {
|
if (isNil "_WeaponCacheEntry") then {
|
||||||
_WeaponCacheEntry = _weapon call FUNC(readWeaponDataFromConfig);
|
_WeaponCacheEntry = _weapon call FUNC(readWeaponDataFromConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable", "_muzzleVelocityVariationSD"];
|
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable", "_muzzleVelocityVariationSD"];
|
||||||
@ -120,8 +120,26 @@ if (_caliber * _bulletLength * _bulletMass * _barrelTwist > 0) then {
|
|||||||
_stabilityFactor = [_caliber, _bulletLength, _bulletMass, _barrelTwist, _muzzleVelocity, _temperature, _barometricPressure] call FUNC(calculateStabilityFactor);
|
_stabilityFactor = [_caliber, _bulletLength, _bulletMass, _barrelTwist, _muzzleVelocity, _temperature, _barometricPressure] call FUNC(calculateStabilityFactor);
|
||||||
};
|
};
|
||||||
|
|
||||||
GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000;
|
("ace" callExtension [
|
||||||
|
"ballistics:bullet:new", [
|
||||||
"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17:%18", GVAR(currentbulletID), _ammoCount, _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _transonicStabilityCoef, getPosASL _projectile, _bulletVelocity, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6];
|
_ammoCount,
|
||||||
|
_airFriction,
|
||||||
GVAR(allBullets) pushBack [_projectile, _caliber, _bulletTraceVisible, GVAR(currentbulletID)];
|
_ballisticCoefficients,
|
||||||
|
_velocityBoundaries,
|
||||||
|
_atmosphereModel,
|
||||||
|
_dragModel,
|
||||||
|
_stabilityFactor,
|
||||||
|
_twistDirection,
|
||||||
|
_transonicStabilityCoef,
|
||||||
|
_bulletVelocity,
|
||||||
|
EGVAR(common,mapLatitude),
|
||||||
|
EGVAR(weather,currentTemperature),
|
||||||
|
EGVAR(common,mapAltitude),
|
||||||
|
EGVAR(weather,currentHumidity),
|
||||||
|
EGVAR(weather,currentOvercast),
|
||||||
|
CBA_missionTime toFixed 6
|
||||||
|
]
|
||||||
|
]) params ["_id", "_code"];
|
||||||
|
if (_code == 0) then {
|
||||||
|
GVAR(allBullets) set [_id, [_projectile, _caliber, _bulletTraceVisible]];
|
||||||
|
};
|
||||||
|
@ -21,7 +21,14 @@ if (!GVAR(enabled)) exitWith {};
|
|||||||
private _initStartTime = diag_tickTime;
|
private _initStartTime = diag_tickTime;
|
||||||
private _mapSize = worldSize;
|
private _mapSize = worldSize;
|
||||||
|
|
||||||
if (("ace_advanced_ballistics" callExtension format["init:%1:%2", worldName, _mapSize]) == "Terrain already initialized") exitWith {
|
(
|
||||||
|
"ace" callExtension ["ballistics:map:init", [worldName, _mapSize]]
|
||||||
|
) params ["_data", "_code"];
|
||||||
|
if (_code != 0) exitWith {
|
||||||
|
ERROR("Error initializing map")
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_data == "true") exitWith {
|
||||||
INFO_1("Terrain already initialized [world: %1]",worldName);
|
INFO_1("Terrain already initialized [world: %1]",worldName);
|
||||||
#ifdef DEBUG_MODE_FULL
|
#ifdef DEBUG_MODE_FULL
|
||||||
systemChat "AdvancedBallistics: Terrain already initialized";
|
systemChat "AdvancedBallistics: Terrain already initialized";
|
||||||
@ -53,8 +60,7 @@ INFO_2("Starting Terrain Extension [cells: %1] [world: %2]",_gridCells,worldName
|
|||||||
private _gridCenter = [_x + 25, _y + 25];
|
private _gridCenter = [_x + 25, _y + 25];
|
||||||
private _gridHeight = round(getTerrainHeightASL _gridCenter);
|
private _gridHeight = round(getTerrainHeightASL _gridCenter);
|
||||||
private _gridNumObjects = count (_gridCenter nearObjects ["Building", 50]);
|
private _gridNumObjects = count (_gridCenter nearObjects ["Building", 50]);
|
||||||
private _gridSurfaceIsWater = parseNumber (surfaceIsWater _gridCenter);
|
"ace" callExtension ["ballistics:map:set", [GVAR(currentGrid), _gridHeight, _gridNumObjects, surfaceIsWater _gridCenter]];
|
||||||
"ace_advanced_ballistics" callExtension format["set:%1:%2:%3", _gridHeight, _gridNumObjects, _gridSurfaceIsWater];
|
|
||||||
GVAR(currentGrid) = GVAR(currentGrid) + 1;
|
GVAR(currentGrid) = GVAR(currentGrid) + 1;
|
||||||
if (GVAR(currentGrid) >= _gridCells) exitWith {};
|
if (GVAR(currentGrid) >= _gridCells) exitWith {};
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ if (_transonicStabilityCoef == 0) then {
|
|||||||
_transonicStabilityCoef = 0.5;
|
_transonicStabilityCoef = 0.5;
|
||||||
};
|
};
|
||||||
private _dragModel = getNumber(_ammoConfig >> "ACE_dragModel");
|
private _dragModel = getNumber(_ammoConfig >> "ACE_dragModel");
|
||||||
if (!(_dragModel in [1, 2, 5, 6, 7, 8])) then {
|
if !(_dragModel in [1, 2, 5, 6, 7, 8]) then {
|
||||||
_dragModel = 1;
|
_dragModel = 1;
|
||||||
};
|
};
|
||||||
private _ballisticCoefficients = getArray(_ammoConfig >> "ACE_ballisticCoefficients");
|
private _ballisticCoefficients = getArray(_ammoConfig >> "ACE_ballisticCoefficients");
|
||||||
|
@ -5,7 +5,9 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)];
|
|||||||
[LSTRING(enabled_DisplayName), LSTRING(enabled_Description)],
|
[LSTRING(enabled_DisplayName), LSTRING(enabled_Description)],
|
||||||
_category,
|
_category,
|
||||||
false,
|
false,
|
||||||
1
|
1,
|
||||||
|
{[QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)},
|
||||||
|
true // Needs mission restart
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -45,5 +47,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)];
|
|||||||
[LSTRING(simulationInterval_DisplayName), LSTRING(simulationInterval_Description)],
|
[LSTRING(simulationInterval_DisplayName), LSTRING(simulationInterval_Description)],
|
||||||
_category,
|
_category,
|
||||||
[0, 0.2, 0.05, 2],
|
[0, 0.2, 0.05, 2],
|
||||||
1
|
1,
|
||||||
|
{[QGVAR(simulationInterval), _this] call EFUNC(common,cbaSettings_settingChanged)},
|
||||||
|
true // Needs mission restart
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<Hungarian>Fejlett ballisztika</Hungarian>
|
<Hungarian>Fejlett ballisztika</Hungarian>
|
||||||
<Russian>Продвинутая баллистика</Russian>
|
<Russian>Продвинутая баллистика</Russian>
|
||||||
<Italian>Balistica Avanzata</Italian>
|
<Italian>Balistica Avanzata</Italian>
|
||||||
<Japanese>アドバンスド弾道計算</Japanese>
|
<Japanese>高度な弾道計算</Japanese>
|
||||||
<Korean>고급 탄도학</Korean>
|
<Korean>고급 탄도학</Korean>
|
||||||
<Chinese>先進彈道系統</Chinese>
|
<Chinese>先進彈道系統</Chinese>
|
||||||
<Chinesesimp>进阶弹道系统</Chinesesimp>
|
<Chinesesimp>进阶弹道系统</Chinesesimp>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
<Hungarian>Fejlett ballisztika</Hungarian>
|
<Hungarian>Fejlett ballisztika</Hungarian>
|
||||||
<Russian>Продвинутая баллистика</Russian>
|
<Russian>Продвинутая баллистика</Russian>
|
||||||
<Italian>Balistica Avanzata</Italian>
|
<Italian>Balistica Avanzata</Italian>
|
||||||
<Japanese>アドバンスド弾道計算を有効化</Japanese>
|
<Japanese>高度な弾道計算を有効化</Japanese>
|
||||||
<Korean>고급 탄도학</Korean>
|
<Korean>고급 탄도학</Korean>
|
||||||
<Chinese>先進彈道系統</Chinese>
|
<Chinese>先進彈道系統</Chinese>
|
||||||
<Chinesesimp>进阶弹道系统</Chinesesimp>
|
<Chinesesimp>进阶弹道系统</Chinesesimp>
|
||||||
@ -80,7 +80,7 @@
|
|||||||
<Hungarian>Engedélyezi a fejlett ballisztikát</Hungarian>
|
<Hungarian>Engedélyezi a fejlett ballisztikát</Hungarian>
|
||||||
<Russian>Включает продвинутую баллистику</Russian>
|
<Russian>Включает продвинутую баллистику</Russian>
|
||||||
<Italian>Abilita Balistica Avanzata</Italian>
|
<Italian>Abilita Balistica Avanzata</Italian>
|
||||||
<Japanese>アドバンスド弾道計算は高度な弾道計算処理を有効化します。</Japanese>
|
<Japanese>高度な弾道計算を有効化します。</Japanese>
|
||||||
<Korean>고급 탄도학을 적용합니다</Korean>
|
<Korean>고급 탄도학을 적용합니다</Korean>
|
||||||
<Chinese>啟用先進彈道系統</Chinese>
|
<Chinese>啟用先進彈道系統</Chinese>
|
||||||
<Chinesesimp>启用进阶弹道系统</Chinesesimp>
|
<Chinesesimp>启用进阶弹道系统</Chinesesimp>
|
||||||
@ -280,7 +280,7 @@
|
|||||||
<Hungarian>Meghatározza a játékos körüli hatókört (méterben), ahol a lövedékek fejlett ballisztikát használnak</Hungarian>
|
<Hungarian>Meghatározza a játékos körüli hatókört (méterben), ahol a lövedékek fejlett ballisztikát használnak</Hungarian>
|
||||||
<Russian>Определяет радиус вокруг игрока (в метрах), в котором продвинутая баллистика применяется к снарядам</Russian>
|
<Russian>Определяет радиус вокруг игрока (в метрах), в котором продвинутая баллистика применяется к снарядам</Russian>
|
||||||
<Italian>Definisce il raggio attorno al giocatore (in metri) entro il quale la Balistica Avanzata è applicata ai proiettili</Italian>
|
<Italian>Definisce il raggio attorno al giocatore (in metri) entro il quale la Balistica Avanzata è applicata ai proiettili</Italian>
|
||||||
<Japanese>アドバンスド弾道計算の適用半径範囲 (プレイヤー中心、メートル単位) を定義します。</Japanese>
|
<Japanese>高度な弾道計算が飛翔体に適用される半径距離 (プレイヤー中心、メートル単位) を定義します。</Japanese>
|
||||||
<Korean>플레이어 주위의 발사체를 고급 탄도학으로 정의하는 범위를 정합니다(미터)</Korean>
|
<Korean>플레이어 주위의 발사체를 고급 탄도학으로 정의하는 범위를 정합니다(미터)</Korean>
|
||||||
<Chinese>以玩家的半徑距離(公尺)定義先進彈道系統啟用範圍</Chinese>
|
<Chinese>以玩家的半徑距離(公尺)定義先進彈道系統啟用範圍</Chinese>
|
||||||
<Chinesesimp>定义玩家周围的半径(米),在这个半径内,进阶弹道系统会被启用</Chinesesimp>
|
<Chinesesimp>定义玩家周围的半径(米),在这个半径内,进阶弹道系统会被启用</Chinesesimp>
|
||||||
@ -297,7 +297,7 @@
|
|||||||
<Russian>Этот модуль включает симуляцию продвинутой баллистики - при этом на траекторию полета снаряда влияют различные параметры, такие как температура воздуха, атмосферное давление, влажность, гравитация, тип боеприпаса и оружия, из которого произвели выстрел.</Russian>
|
<Russian>Этот модуль включает симуляцию продвинутой баллистики - при этом на траекторию полета снаряда влияют различные параметры, такие как температура воздуха, атмосферное давление, влажность, гравитация, тип боеприпаса и оружия, из которого произвели выстрел.</Russian>
|
||||||
<Spanish>Este módulo permite la simulación balística avanzada - es decir, la trayectoria de los proyectiles está influenciada por variables como la temperatura del aire, la presión atmosférica, la humedad, la gravedad, el tipo de municiones y el arma desde el que fue disparada.</Spanish>
|
<Spanish>Este módulo permite la simulación balística avanzada - es decir, la trayectoria de los proyectiles está influenciada por variables como la temperatura del aire, la presión atmosférica, la humedad, la gravedad, el tipo de municiones y el arma desde el que fue disparada.</Spanish>
|
||||||
<Italian>Questo modulo abilita la simulazione della Balistica Avanzata - essa comporta che la traiettoria dei proiettili è influenzata da variabili come la temperatura dell'aria, pressione atmosferica, umidità, gravità, il tipo di munizione e l'arma da cui è sparata.</Italian>
|
<Italian>Questo modulo abilita la simulazione della Balistica Avanzata - essa comporta che la traiettoria dei proiettili è influenzata da variabili come la temperatura dell'aria, pressione atmosferica, umidità, gravità, il tipo di munizione e l'arma da cui è sparata.</Italian>
|
||||||
<Japanese>アドバンスド弾道計算のシミュレーションを有効化します。 弾道は気温・気圧・湿度・重力・弾薬の種類・発射する武器などの変化による影響を受けるようになります。</Japanese>
|
<Japanese>高度な弾道計算のシミュレーションを有効化します。 弾道は気温・気圧・湿度・重力・弾薬の種類・発射する武器などの変化による影響を受けるようになります。</Japanese>
|
||||||
<Korean>이 모듈은 고급 탄도학을 적용시킵니다 - 이는 발사체의 궤적이 기온, 대기압, 습도, 중력, 탄환의 종류와 어느 무기에서 발사되는지에 따라 영향을 받습니다.</Korean>
|
<Korean>이 모듈은 고급 탄도학을 적용시킵니다 - 이는 발사체의 궤적이 기온, 대기압, 습도, 중력, 탄환의 종류와 어느 무기에서 발사되는지에 따라 영향을 받습니다.</Korean>
|
||||||
<Chinese>該模塊實現先進的彈道仿真 - 這意味著子彈的軌跡是由空氣溫度、大氣壓力、濕度、重力、彈藥類型以及射擊的武器所影響</Chinese>
|
<Chinese>該模塊實現先進的彈道仿真 - 這意味著子彈的軌跡是由空氣溫度、大氣壓力、濕度、重力、彈藥類型以及射擊的武器所影響</Chinese>
|
||||||
<Chinesesimp>该模块实现增强的弹道模拟—子弹的轨迹由空气温度、大气压力、湿度、重力、弹药类型和射击的武器等变量所影响</Chinesesimp>
|
<Chinesesimp>该模块实现增强的弹道模拟—子弹的轨迹由空气温度、大气压力、湿度、重力、弹药类型和射击的武器等变量所影响</Chinesesimp>
|
||||||
|
@ -9,3 +9,5 @@ PREP(handleStaminaBar);
|
|||||||
PREP(mainLoop);
|
PREP(mainLoop);
|
||||||
PREP(moduleSettings);
|
PREP(moduleSettings);
|
||||||
PREP(removeDutyFactor);
|
PREP(removeDutyFactor);
|
||||||
|
PREP(renderDebugLines);
|
||||||
|
PREP(updateStaminaBar);
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
if (!hasInterface) exitWith {};
|
if (!hasInterface) exitWith {};
|
||||||
|
|
||||||
|
#ifdef DEBUG_MODE_FULL
|
||||||
|
call FUNC(renderDebugLines);
|
||||||
|
#endif
|
||||||
|
|
||||||
// recheck weapon inertia after weapon swap, change of attachments or switching unit
|
// recheck weapon inertia after weapon swap, change of attachments or switching unit
|
||||||
["weapon", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
|
["weapon", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
|
||||||
["loadout", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
|
["loadout", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
|
||||||
@ -10,6 +14,8 @@ if (!hasInterface) exitWith {};
|
|||||||
["CBA_settingsInitialized", {
|
["CBA_settingsInitialized", {
|
||||||
if (!GVAR(enabled)) exitWith {};
|
if (!GVAR(enabled)) exitWith {};
|
||||||
|
|
||||||
|
[QEGVAR(ui,hideHud), LINKFUNC(updateStaminaBar)] call CBA_fnc_addEventHandler;
|
||||||
|
|
||||||
["baseline", {
|
["baseline", {
|
||||||
private _fatigue = ACE_player getVariable [QGVAR(aimFatigue), 0];
|
private _fatigue = ACE_player getVariable [QGVAR(aimFatigue), 0];
|
||||||
switch (stance ACE_player) do {
|
switch (stance ACE_player) do {
|
||||||
@ -33,25 +39,23 @@ if (!hasInterface) exitWith {};
|
|||||||
GVAR(ppeBlackout) ppEffectCommit 0.4;
|
GVAR(ppeBlackout) ppEffectCommit 0.4;
|
||||||
|
|
||||||
// - GVAR updating and initialization -----------------------------------------
|
// - GVAR updating and initialization -----------------------------------------
|
||||||
["unit", LINKFUNC(handlePlayerChanged), true] call CBA_fnc_addPlayerEventHandler;
|
["unit", LINKFUNC(handlePlayerChanged)] call CBA_fnc_addPlayerEventHandler;
|
||||||
|
|
||||||
["visibleMap", {
|
["visibleMap", {
|
||||||
params ["", "_visibleMap"]; // command visibleMap is updated one frame later
|
params ["", "_visibleMap"]; // command visibleMap is updated one frame later
|
||||||
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
(uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull]) ctrlShow (!_visibleMap && isNull objectParent ACE_player);
|
||||||
_staminaBarContainer ctrlShow ((!_visibleMap) && {(vehicle ACE_player) == ACE_player});
|
|
||||||
}, true] call CBA_fnc_addPlayerEventHandler;
|
}, true] call CBA_fnc_addPlayerEventHandler;
|
||||||
["vehicle", {
|
["vehicle", {
|
||||||
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
(uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull]) ctrlShow (!visibleMap && isNull objectParent ACE_player);
|
||||||
_staminaBarContainer ctrlShow ((!visibleMap) && {(vehicle ACE_player) == ACE_player});
|
|
||||||
}, true] call CBA_fnc_addPlayerEventHandler;
|
}, true] call CBA_fnc_addPlayerEventHandler;
|
||||||
|
|
||||||
// - Duty factors -------------------------------------------------------------
|
// - Duty factors -------------------------------------------------------------
|
||||||
if (GVAR(medicalLoaded)) then {
|
if (GETEGVAR(medical,enabled,false)) then {
|
||||||
[QEGVAR(medical,pain), { // 0->1.0, 0.5->1.05, 1->1.1
|
[QEGVAR(medical,pain), { // 0->1.0, 0.5->1.05, 1->1.1
|
||||||
linearConversion [0, 1, (_this getVariable [QEGVAR(medical,pain), 0]), 1, 1.1, true];
|
linearConversion [0, 1, _this getVariable [QEGVAR(medical,pain), 0], 1, 1.1, true];
|
||||||
}] call FUNC(addDutyFactor);
|
}] call FUNC(addDutyFactor);
|
||||||
[QEGVAR(medical,bloodVolume), { // 6->1.0, 5->1.167, 4->1.33
|
[QEGVAR(medical,bloodVolume), { // 6->1.0, 5->1.167, 4->1.33
|
||||||
linearConversion [6, 0, (_this getVariable [QEGVAR(medical,bloodVolume), 6]), 1, 2, true];
|
linearConversion [6, 0, _this getVariable [QEGVAR(medical,bloodVolume), 6], 1, 2, true];
|
||||||
}] call FUNC(addDutyFactor);
|
}] call FUNC(addDutyFactor);
|
||||||
};
|
};
|
||||||
if (["ace_dragging"] call EFUNC(common,isModLoaded)) then {
|
if (["ace_dragging"] call EFUNC(common,isModLoaded)) then {
|
||||||
@ -62,7 +66,7 @@ if (!hasInterface) exitWith {};
|
|||||||
// Weather has an off switch, Dragging & Medical don't.
|
// Weather has an off switch, Dragging & Medical don't.
|
||||||
if (missionNamespace getVariable [QEGVAR(weather,enabled), false]) then {
|
if (missionNamespace getVariable [QEGVAR(weather,enabled), false]) then {
|
||||||
[QEGVAR(weather,temperature), { // 35->1, 45->2
|
[QEGVAR(weather,temperature), { // 35->1, 45->2
|
||||||
linearConversion [35, 45, (missionNamespace getVariable [QEGVAR(weather,currentTemperature), 25]), 1, 2, true];
|
linearConversion [35, 45, missionNamespace getVariable [QEGVAR(weather,currentTemperature), 25], 1, 2, true];
|
||||||
}] call FUNC(addDutyFactor);
|
}] call FUNC(addDutyFactor);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,6 +13,5 @@ GVAR(dutyList) = createHashMap;
|
|||||||
GVAR(setAnimExclusions) = [];
|
GVAR(setAnimExclusions) = [];
|
||||||
GVAR(inertia) = 0;
|
GVAR(inertia) = 0;
|
||||||
GVAR(inertiaCache) = createHashMap;
|
GVAR(inertiaCache) = createHashMap;
|
||||||
GVAR(medicalLoaded) = ["ace_medical"] call EFUNC(common,isModLoaded);
|
|
||||||
|
|
||||||
ADDON = true;
|
ADDON = true;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: BaerMitUmlaut
|
* Author: BaerMitUmlaut
|
||||||
* Calculates the duty of the current animation.
|
* Calculates the duty ('postureWeight') of the current animation.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* 0: Unit <OBJECT>
|
* 0: Unit <OBJECT>
|
||||||
|
@ -1,54 +1,74 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: BaerMitUmlaut
|
* Author: BaerMitUmlaut, ulteq
|
||||||
* Calculates the current metabolic costs for a unit.
|
* Calculates the current metabolic costs.
|
||||||
* Calculation is done according to the Pandolf/Wojtowicz formulas.
|
* Calculation is done according to the Pandolf/Wojtowicz formulas.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* 0: Unit <OBJECT>
|
* 0: Duty of animation
|
||||||
* 1: Speed <NUMBER>
|
* 1: Mass of unit <NUMBER>
|
||||||
|
* 2: Terrain gradient <NUMBER>
|
||||||
|
* 3: Terrain factor <NUMBER>
|
||||||
|
* 4: Speed <NUMBER>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* Metabolic cost <NUMBER>
|
* Metabolic cost <NUMBER>
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* [player, 3.3] call ace_advanced_fatigue_fnc_getMetabolicCosts
|
* [1, 840, 20, 1, 4] call ace_advanced_fatigue_fnc_getMetabolicCosts
|
||||||
*
|
*
|
||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
params ["_unit", "_velocity"];
|
|
||||||
|
|
||||||
private _gearMass = ((_unit getVariable [QEGVAR(movement,totalLoad), loadAbs _unit]) / 22.046) * GVAR(loadFactor);
|
params ["_duty", "_gearMass", "_terrainGradient", "_terrainFactor", "_speed"];
|
||||||
|
|
||||||
private _terrainAngle = asin (1 - ((surfaceNormal getPosASL _unit) select 2));
|
|
||||||
private _terrainGradient = (_terrainAngle / 45 min 1) * 5 * GVAR(terrainGradientFactor);
|
|
||||||
private _duty = GVAR(animDuty);
|
|
||||||
|
|
||||||
{
|
|
||||||
if (_x isEqualType 0) then {
|
|
||||||
_duty = _duty * _x;
|
|
||||||
} else {
|
|
||||||
_duty = _duty * (_unit call _x);
|
|
||||||
};
|
|
||||||
} forEach (values GVAR(dutyList));
|
|
||||||
|
|
||||||
if (GVAR(isSwimming)) then {
|
|
||||||
_terrainGradient = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Metabolic cost for walking and running is different
|
// Metabolic cost for walking and running is different
|
||||||
if (_velocity > 2) then {
|
if (_speed > 2) then {
|
||||||
// Running
|
// Running
|
||||||
|
#ifdef DEBUG_MODE_FULL
|
||||||
|
private _baseline = 2.1 * SIM_BODYMASS + 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2) + (SIM_BODYMASS + _gearMass) * 0.9 * (_speed ^ 2);
|
||||||
|
private _graded = 2.1 * SIM_BODYMASS + 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2) + _terrainFactor * (SIM_BODYMASS + _gearMass) * (0.9 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient);
|
||||||
|
private _terrainImpact = abs ((_graded / _baseline) - 1);
|
||||||
|
hintSilent format ["FwdAngle: %1 | SideAngle: %2 \n TerrainFactor: %3 | TerrainGradient: %4 \n TerrainImpact: %5 \n Speed: %6 | CarriedLoad: %7 \n Duty: %8 | Work: %9",
|
||||||
|
_fwdAngle toFixed 1,
|
||||||
|
_sideAngle toFixed 1,
|
||||||
|
_terrainFactor toFixed 2,
|
||||||
|
_terrainGradient toFixed 1,
|
||||||
|
_terrainImpact toFixed 2,
|
||||||
|
_speed toFixed 2,
|
||||||
|
_gearMass toFixed 1,
|
||||||
|
_duty toFixed 2,
|
||||||
|
round (_graded * BIOMECH_EFFICIENCY * _duty)
|
||||||
|
];
|
||||||
|
#endif
|
||||||
|
|
||||||
(
|
(
|
||||||
2.10 * SIM_BODYMASS
|
2.1 * SIM_BODYMASS
|
||||||
+ 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
|
+ 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
|
||||||
+ (SIM_BODYMASS + _gearMass) * (0.9 * (_velocity ^ 2) + 0.66 * _velocity * _terrainGradient)
|
+ _terrainFactor * (SIM_BODYMASS + _gearMass) * (0.9 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient)
|
||||||
) * 0.23 * _duty
|
) * BIOMECH_EFFICIENCY * _duty
|
||||||
} else {
|
} else {
|
||||||
// Walking
|
// Walking
|
||||||
|
#ifdef DEBUG_MODE_FULL
|
||||||
|
private _baseline = 1.05 * SIM_BODYMASS + 2 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2) + (SIM_BODYMASS + _gearMass) * 1.15 * (_speed ^ 2);
|
||||||
|
private _graded = 1.05 * SIM_BODYMASS + 2 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2) + _terrainFactor * (SIM_BODYMASS + _gearMass) * (1.15 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient);
|
||||||
|
private _terrainImpact = abs ((_graded / _baseline) - 1);
|
||||||
|
hintSilent format ["FwdAngle: %1 | SideAngle: %2 \n TerrainFactor: %3 | TerrainGradient: %4 \n TerrainImpact: %5 \n Speed: %6 | CarriedLoad: %7 \n Duty: %8 | Work: %9",
|
||||||
|
_fwdAngle toFixed 1,
|
||||||
|
_sideAngle toFixed 1,
|
||||||
|
_terrainFactor toFixed 2,
|
||||||
|
_terrainGradient toFixed 1,
|
||||||
|
_terrainImpact toFixed 2,
|
||||||
|
_speed toFixed 2,
|
||||||
|
_gearMass toFixed 1,
|
||||||
|
_duty toFixed 2,
|
||||||
|
round (_graded * BIOMECH_EFFICIENCY * _duty)
|
||||||
|
];
|
||||||
|
#endif
|
||||||
|
|
||||||
(
|
(
|
||||||
1.05 * SIM_BODYMASS
|
1.05 * SIM_BODYMASS
|
||||||
+ 2 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
|
+ 2 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
|
||||||
+ (SIM_BODYMASS + _gearMass) * (1.15 * (_velocity ^ 2) + 0.66 * _velocity * _terrainGradient)
|
+ _terrainFactor * (SIM_BODYMASS + _gearMass) * (1.15 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient)
|
||||||
) * 0.23 * _duty
|
) * BIOMECH_EFFICIENCY * _duty
|
||||||
};
|
};
|
||||||
|
@ -1,44 +1,44 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: BaerMitUmlaut
|
* Author: BaerMitUmlaut, ulteq
|
||||||
* Handles any audible, visual and physical effects of fatigue.
|
* Handles any audible, visual and physical effects of fatigue.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* 0: Unit <OBJECT>
|
* 0: Unit <OBJECT>
|
||||||
* 1: Fatigue <NUMBER>
|
* 1: Fatigue <NUMBER>
|
||||||
* 2: Speed <NUMBER>
|
* 2: Overexhausted <BOOL>
|
||||||
* 3: Overexhausted <BOOL>
|
* 3: Forward Angle <NUMBER>
|
||||||
|
* 4: Side Angle <NUMBER>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* None
|
* None
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* [_player, 0.5, 3.3, true] call ace_advanced_fatigue_fnc_handleEffects
|
* [_player, 0.5, 3.3, true, 0, 0] call ace_advanced_fatigue_fnc_handleEffects
|
||||||
*
|
*
|
||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
params ["_unit", "_fatigue", "_speed", "_overexhausted"];
|
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
params ["_unit", "_fatigue", "_overexhausted", "_fwdAngle", "_sideAngle"];
|
||||||
systemChat str _fatigue;
|
|
||||||
systemChat str vectorMagnitude velocity _unit;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// - Audible effects ----------------------------------------------------------
|
// - Audible effects ----------------------------------------------------------
|
||||||
GVAR(lastBreath) = GVAR(lastBreath) + 1;
|
GVAR(lastBreath) = GVAR(lastBreath) + 1;
|
||||||
|
|
||||||
if (_fatigue > 0.4 && {GVAR(lastBreath) > (_fatigue * -10 + 9)} && {!underwater _unit}) then {
|
if (_fatigue > 0.4 && {GVAR(lastBreath) > (_fatigue * -10 + 9)} && {!underwater _unit}) then {
|
||||||
if (!isGameFocused) exitWith {};
|
if (!isGameFocused) exitWith {};
|
||||||
|
|
||||||
switch (true) do {
|
switch (true) do {
|
||||||
case (_fatigue < 0.6): {
|
case (_fatigue < 0.6): {
|
||||||
playSound (QGVAR(breathLow) + str(floor random 6));
|
playSound (QGVAR(breathLow) + str (floor random 6));
|
||||||
};
|
};
|
||||||
case (_fatigue < 0.85): {
|
case (_fatigue < 0.85): {
|
||||||
playSound (QGVAR(breathMid) + str(floor random 6));
|
playSound (QGVAR(breathMid) + str (floor random 6));
|
||||||
};
|
};
|
||||||
default {
|
default {
|
||||||
playSound (QGVAR(breathMax) + str(floor random 6));
|
playSound (QGVAR(breathMax) + str (floor random 6));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
GVAR(lastBreath) = 0;
|
GVAR(lastBreath) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,31 +62,35 @@ if (GVAR(isSwimming)) exitWith {
|
|||||||
if (GVAR(setAnimExclusions) isEqualTo []) then {
|
if (GVAR(setAnimExclusions) isEqualTo []) then {
|
||||||
_unit setAnimSpeedCoef linearConversion [0.7, 0.9, _fatigue, 1, 0.5, true];
|
_unit setAnimSpeedCoef linearConversion [0.7, 0.9, _fatigue, 1, 0.5, true];
|
||||||
};
|
};
|
||||||
if ((isSprintAllowed _unit) && {_fatigue > 0.7}) then {
|
|
||||||
|
if (isSprintAllowed _unit && _fatigue > 0.7) then { // small checks like these are faster without lazy eval
|
||||||
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
||||||
} else {
|
} else {
|
||||||
if ((!isSprintAllowed _unit) && {_fatigue < 0.7}) then {
|
if (!isSprintAllowed _unit && _fatigue < 0.7) then {
|
||||||
[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if ((getAnimSpeedCoef _unit) != 1) then {
|
|
||||||
if (GVAR(setAnimExclusions) isEqualTo []) then {
|
// If other components are setting setAnimSpeedCoef, do not change animSpeedCoef
|
||||||
TRACE_1("reset",getAnimSpeedCoef _unit);
|
if (getAnimSpeedCoef _unit != 1 && {GVAR(setAnimExclusions) isEqualTo []}) then {
|
||||||
_unit setAnimSpeedCoef 1;
|
TRACE_1("reset",getAnimSpeedCoef _unit);
|
||||||
};
|
_unit setAnimSpeedCoef 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_overexhausted) then {
|
if (!isForcedWalk _unit && _fatigue >= 1) then { // small checks like these are faster without lazy eval
|
||||||
[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
||||||
|
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
||||||
} else {
|
} else {
|
||||||
if (isForcedWalk _unit && {_fatigue < 0.7}) then {
|
if (isForcedWalk _unit && _fatigue < 0.7) then {
|
||||||
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
||||||
|
[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
||||||
} else {
|
} else {
|
||||||
if ((isSprintAllowed _unit) && {_fatigue > 0.7}) then {
|
// Forward angle is the slope of the terrain, side angle simulates the unevenness/roughness of the terrain
|
||||||
|
if (isSprintAllowed _unit && {_fatigue > 0.7 || abs _fwdAngle > 20 || abs _sideAngle > 20}) then {
|
||||||
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
||||||
} else {
|
} else {
|
||||||
if ((!isSprintAllowed _unit) && {_fatigue < 0.6}) then {
|
if (!isSprintAllowed _unit && _fatigue < 0.6 && abs _fwdAngle < 20 && abs _sideAngle < 20) then {
|
||||||
[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: BaerMitUmlaut
|
* Author: BaerMitUmlaut, ulteq
|
||||||
* Handles switching units (once on init and afterwards via Zeus).
|
* Handles switching units (once on init and afterwards via Zeus). Also handles CBA setting change for performance factor.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* 0: New Unit <OBJECT>
|
* 0: New Unit <OBJECT>
|
||||||
@ -15,20 +15,24 @@
|
|||||||
*
|
*
|
||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
params ["_newUnit", "_oldUnit"];
|
params ["_newUnit", "_oldUnit"];
|
||||||
|
|
||||||
TRACE_2("unit changed",_newUnit,_oldUnit);
|
TRACE_2("unit changed",_newUnit,_oldUnit);
|
||||||
|
|
||||||
if !(isNull _oldUnit) then {
|
if (!isNull _oldUnit) then {
|
||||||
|
TRACE_1("remove old",_oldUnit getVariable QGVAR(animHandler));
|
||||||
|
|
||||||
_oldUnit enableStamina true;
|
_oldUnit enableStamina true;
|
||||||
_oldUnit removeEventHandler ["AnimChanged", _oldUnit getVariable [QGVAR(animHandler), -1]];
|
_oldUnit removeEventHandler ["AnimChanged", _oldUnit getVariable [QGVAR(animHandler), -1]];
|
||||||
_oldUnit setVariable [QGVAR(animHandler), nil];
|
_oldUnit setVariable [QGVAR(animHandler), nil];
|
||||||
TRACE_1("remove old",_oldUnit getVariable QGVAR(animHandler));
|
|
||||||
|
|
||||||
_oldUnit setVariable [QGVAR(ae1Reserve), GVAR(ae1Reserve)];
|
_oldUnit setVariable [QGVAR(ae1Reserve), GVAR(ae1Reserve)];
|
||||||
_oldUnit setVariable [QGVAR(ae2Reserve), GVAR(ae2Reserve)];
|
_oldUnit setVariable [QGVAR(ae2Reserve), GVAR(ae2Reserve)];
|
||||||
_oldUnit setVariable [QGVAR(anReserve), GVAR(anReserve)];
|
_oldUnit setVariable [QGVAR(anReserve), GVAR(anReserve)];
|
||||||
_oldUnit setVariable [QGVAR(anFatigue), GVAR(anFatigue)];
|
_oldUnit setVariable [QGVAR(anFatigue), GVAR(anFatigue)];
|
||||||
_oldUnit setVariable [QGVAR(muscleDamage), GVAR(muscleDamage)];
|
_oldUnit setVariable [QGVAR(muscleDamage), GVAR(muscleDamage)];
|
||||||
|
_oldUnit setVariable [QGVAR(respiratoryRate), GVAR(respiratoryRate)];
|
||||||
};
|
};
|
||||||
|
|
||||||
_newUnit enableStamina false;
|
_newUnit enableStamina false;
|
||||||
@ -38,6 +42,7 @@ if (_newUnit getVariable [QGVAR(animHandler), -1] == -1) then {
|
|||||||
private _animHandler = _newUnit addEventHandler ["AnimChanged", {
|
private _animHandler = _newUnit addEventHandler ["AnimChanged", {
|
||||||
GVAR(animDuty) = _this call FUNC(getAnimDuty);
|
GVAR(animDuty) = _this call FUNC(getAnimDuty);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
TRACE_1("add new",_animHandler);
|
TRACE_1("add new",_animHandler);
|
||||||
_newUnit setVariable [QGVAR(animHandler), _animHandler];
|
_newUnit setVariable [QGVAR(animHandler), _animHandler];
|
||||||
};
|
};
|
||||||
@ -47,18 +52,27 @@ GVAR(ae2Reserve) = _newUnit getVariable [QGVAR(ae2Reserve), AE2_MAXRESERVE]
|
|||||||
GVAR(anReserve) = _newUnit getVariable [QGVAR(anReserve), AN_MAXRESERVE];
|
GVAR(anReserve) = _newUnit getVariable [QGVAR(anReserve), AN_MAXRESERVE];
|
||||||
GVAR(anFatigue) = _newUnit getVariable [QGVAR(anFatigue), 0];
|
GVAR(anFatigue) = _newUnit getVariable [QGVAR(anFatigue), 0];
|
||||||
GVAR(muscleDamage) = _newUnit getVariable [QGVAR(muscleDamage), 0];
|
GVAR(muscleDamage) = _newUnit getVariable [QGVAR(muscleDamage), 0];
|
||||||
|
GVAR(respiratoryRate) = _newUnit getVariable [QGVAR(respiratoryRate), 0];
|
||||||
|
|
||||||
// Clean variables for respawning units
|
// Clean variables for respawning units
|
||||||
{
|
{
|
||||||
_newUnit setVariable [_x, nil];
|
_newUnit setVariable [_x, nil];
|
||||||
} forEach [QGVAR(ae1Reserve), QGVAR(ae2Reserve), QGVAR(anReserve), QGVAR(anFatigue), QGVAR(muscleDamage)];
|
} forEach [QGVAR(ae1Reserve), QGVAR(ae2Reserve), QGVAR(anReserve), QGVAR(anFatigue), QGVAR(muscleDamage), QGVAR(respiratoryRate)];
|
||||||
|
|
||||||
GVAR(VO2Max) = 35 + 20 * (_newUnit getVariable [QGVAR(performanceFactor), GVAR(performanceFactor)]);
|
GVAR(VO2Max) = 35 + 20 * (_newUnit getVariable [QGVAR(performanceFactor), GVAR(performanceFactor)]);
|
||||||
GVAR(VO2MaxPower) = GVAR(VO2Max) * SIM_BODYMASS * 0.23 * JOULES_PER_ML_O2 / 60;
|
GVAR(VO2MaxPower) = GVAR(VO2Max) * SIM_BODYMASS * BIOMECH_EFFICIENCY * JOULES_PER_ML_O2 / 60;
|
||||||
GVAR(peakPower) = VO2MAX_STRENGTH * GVAR(VO2MaxPower);
|
GVAR(peakPower) = VO2MAX_STRENGTH * GVAR(VO2MaxPower);
|
||||||
|
|
||||||
GVAR(ae1PathwayPower) = GVAR(peakPower) / (13.3 + 16.7 + 113.3) * 13.3 * ANTPERCENT ^ 1.28 * 1.362;
|
GVAR(ae1PathwayPower) = GVAR(peakPower) / (AE1_ATP_RELEASE_RATE + AE2_ATP_RELEASE_RATE + AN_ATP_RELEASE_RATE) * AE1_ATP_RELEASE_RATE * ANTPERCENT ^ 1.28 * 1.362;
|
||||||
GVAR(ae2PathwayPower) = GVAR(peakPower) / (13.3 + 16.7 + 113.3) * 16.7 * ANTPERCENT ^ 1.28 * 1.362;
|
GVAR(ae2PathwayPower) = GVAR(peakPower) / (AE1_ATP_RELEASE_RATE + AE2_ATP_RELEASE_RATE + AN_ATP_RELEASE_RATE) * AE2_ATP_RELEASE_RATE * ANTPERCENT ^ 1.28 * 1.362;
|
||||||
|
GVAR(aePathwayPower) = GVAR(ae1PathwayPower) + GVAR(ae2PathwayPower);
|
||||||
|
GVAR(anPathwayPower) = GVAR(peakPower) - GVAR(aePathwayPower);
|
||||||
|
|
||||||
|
GVAR(aeWattsPerATP) = GVAR(ae1PathwayPower) / AE1_ATP_RELEASE_RATE;
|
||||||
|
GVAR(anWattsPerATP) = GVAR(anPathwayPower) / AN_ATP_RELEASE_RATE;
|
||||||
|
|
||||||
|
GVAR(respiratoryBufferDivisor) = (RESPIRATORY_BUFFER - 1) / RESPIRATORY_BUFFER;
|
||||||
|
GVAR(maxPowerFatigueRatio) = 0.057 / GVAR(peakPower);
|
||||||
|
|
||||||
GVAR(ppeBlackoutLast) = 100;
|
GVAR(ppeBlackoutLast) = 100;
|
||||||
GVAR(lastBreath) = 0;
|
GVAR(lastBreath) = 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: BaerMitUmlaut
|
* Author: BaerMitUmlaut, ulteq
|
||||||
* Main looping function that updates fatigue values.
|
* Main looping function that updates fatigue values.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
@ -17,73 +17,131 @@
|
|||||||
|
|
||||||
// Dead people don't breathe, will also handle null (map intros)
|
// Dead people don't breathe, will also handle null (map intros)
|
||||||
if (!alive ACE_player) exitWith {
|
if (!alive ACE_player) exitWith {
|
||||||
[FUNC(mainLoop), [], 1] call CBA_fnc_waitAndExecute;
|
[LINKFUNC(mainLoop), [], 1] call CBA_fnc_waitAndExecute;
|
||||||
|
|
||||||
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
||||||
_staminaBarContainer ctrlSetFade 1;
|
_staminaBarContainer ctrlSetFade 1;
|
||||||
_staminaBarContainer ctrlCommit 1;
|
_staminaBarContainer ctrlCommit 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private _velocity = velocity ACE_player;
|
||||||
private _oxygen = 0.9; // Default AF oxygen saturation
|
private _normal = surfaceNormal (getPosWorld ACE_player);
|
||||||
if (GVAR(medicalLoaded) && {EGVAR(medical_vitals,simulateSpo2)}) then {
|
private _movementVector = vectorNormalized _velocity;
|
||||||
_oxygen = (ACE_player getVariable [QEGVAR(medical,spo2), 97]) / 100;
|
private _sideVector = vectorNormalized (_movementVector vectorCrossProduct _normal);
|
||||||
};
|
private _fwdAngle = asin (_movementVector select 2);
|
||||||
|
private _sideAngle = asin (_sideVector select 2);
|
||||||
|
|
||||||
private _currentWork = REE;
|
private _currentWork = REE;
|
||||||
private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6;
|
private _currentSpeed = (vectorMagnitude _velocity) min 6;
|
||||||
|
|
||||||
// fix #4481. Diving to the ground is recorded as PRONE stance with running speed velocity. Cap maximum speed to fix.
|
// fix #4481. Diving to the ground is recorded as PRONE stance with running speed velocity. Cap maximum speed to fix.
|
||||||
if (GVAR(isProne)) then {
|
if (GVAR(isProne)) then {
|
||||||
_currentSpeed = _currentSpeed min 1.5;
|
_currentSpeed = _currentSpeed min 1.5;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((vehicle ACE_player == ACE_player) && {_currentSpeed > 0.1} && {isTouchingGround ACE_player || {underwater ACE_player}}) then {
|
// Get the current duty
|
||||||
_currentWork = [ACE_player, _currentSpeed] call FUNC(getMetabolicCosts);
|
private _duty = GVAR(animDuty);
|
||||||
|
|
||||||
|
{
|
||||||
|
if (_x isEqualType 0) then {
|
||||||
|
_duty = _duty * _x;
|
||||||
|
} else {
|
||||||
|
_duty = _duty * (ACE_player call _x);
|
||||||
|
};
|
||||||
|
} forEach (values GVAR(dutyList));
|
||||||
|
|
||||||
|
private _terrainGradient = abs _fwdAngle;
|
||||||
|
private _terrainFactor = 1;
|
||||||
|
private _gearMass = 0 max (((ACE_player getVariable [QEGVAR(movement,totalLoad), loadAbs ACE_player]) / 22.046 - UNDERWEAR_WEIGHT) * GVAR(loadFactor));
|
||||||
|
|
||||||
|
if (isNull objectParent ACE_player && {_currentSpeed > 0.1} && {isTouchingGround ACE_player || {underwater ACE_player}}) then {
|
||||||
|
if (!GVAR(isSwimming)) then {
|
||||||
|
// If the unit is going downhill, it's much less demanding
|
||||||
|
if (_fwdAngle < 0) then {
|
||||||
|
_terrainGradient = 0.15 * _terrainGradient;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to simulate the unevenness/roughness of the terrain
|
||||||
|
if ((getPosATL ACE_player) select 2 < 0.01) then {
|
||||||
|
private _sideGradient = abs (_sideAngle / 45) min 1;
|
||||||
|
|
||||||
|
_terrainFactor = 1 + _sideGradient ^ 4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_currentWork = [_duty, _gearMass, _terrainGradient * GVAR(terrainGradientFactor), _terrainFactor, _currentSpeed] call FUNC(getMetabolicCosts);
|
||||||
_currentWork = _currentWork max REE;
|
_currentWork = _currentWork max REE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Oxygen calculation
|
||||||
|
private _oxygen = if (GETEGVAR(medical,enabled,false) && {EGVAR(medical_vitals,simulateSpo2)}) then { // Defer to medical
|
||||||
|
(ACE_player getVariable [QEGVAR(medical,spo2), 97]) / 100
|
||||||
|
} else {
|
||||||
|
1 - 0.131 * GVAR(respiratoryRate) ^ 2 // Default AF oxygen saturation
|
||||||
|
};
|
||||||
// Calculate muscle damage increase
|
// Calculate muscle damage increase
|
||||||
// Note: Muscle damage recovery is ignored as it takes multiple days
|
GVAR(muscleDamage) = GVAR(muscleDamage) + (_currentWork / GVAR(peakPower)) ^ 3.2 * MUSCLE_TEAR_RATE;
|
||||||
GVAR(muscleDamage) = (GVAR(muscleDamage) + (_currentWork / GVAR(peakPower)) ^ 3.2 * 0.00004) min 1;
|
|
||||||
private _muscleIntegritySqrt = sqrt (1 - GVAR(muscleDamage));
|
// Calculate muscle damage recovery
|
||||||
|
GVAR(muscleDamage) = 0 max (GVAR(muscleDamage) - MUSCLE_RECOVERY * GVAR(recoveryFactor)) min 1;
|
||||||
|
private _muscleIntegrity = 1 - GVAR(muscleDamage);
|
||||||
|
private _muscleFactor = sqrt _muscleIntegrity;
|
||||||
|
|
||||||
// Calculate available power
|
// Calculate available power
|
||||||
private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * _oxygen * _muscleIntegritySqrt;
|
private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * _oxygen * _muscleFactor;
|
||||||
private _ae2PathwayPowerFatigued = GVAR(ae2PathwayPower) * sqrt (GVAR(ae2Reserve) / AE2_MAXRESERVE) * _oxygen * _muscleIntegritySqrt;
|
private _ae2PathwayPowerFatigued = GVAR(ae2PathwayPower) * sqrt (GVAR(ae2Reserve) / AE2_MAXRESERVE) * _oxygen * _muscleFactor;
|
||||||
|
private _aePathwayPowerFatigued = _ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued;
|
||||||
|
private _anPathwayPowerFatigued = GVAR(anPathwayPower) * sqrt (GVAR(anReserve) / AN_MAXRESERVE) * _oxygen * _muscleIntegrity;
|
||||||
|
|
||||||
// Calculate how much power is consumed from each reserve
|
// Calculate how much power is consumed from each reserve
|
||||||
private _ae1Power = _currentWork min _ae1PathwayPowerFatigued;
|
private _ae1Power = _currentWork min _ae1PathwayPowerFatigued;
|
||||||
private _ae2Power = ((_currentWork - _ae1Power) max 0) min _ae2PathwayPowerFatigued;
|
private _ae2Power = (_currentWork - _ae1Power) min _ae2PathwayPowerFatigued;
|
||||||
private _anPower = (_currentWork - _ae1Power - _ae2Power) max 0;
|
private _anPower = 0 max (_currentWork - _ae1Power - _ae2Power);
|
||||||
|
|
||||||
// Remove ATP from reserves for current work
|
// Remove ATP from reserves for current work
|
||||||
GVAR(ae1Reserve) = GVAR(ae1Reserve) - _ae1Power / WATTSPERATP;
|
GVAR(ae1Reserve) = 0 max (GVAR(ae1Reserve) - _ae1Power / GVAR(aeWattsPerATP));
|
||||||
GVAR(ae2Reserve) = GVAR(ae2Reserve) - _ae2Power / WATTSPERATP;
|
GVAR(ae2Reserve) = 0 max (GVAR(ae2Reserve) - _ae2Power / GVAR(aeWattsPerATP));
|
||||||
GVAR(anReserve) = GVAR(anReserve) - _anPower / WATTSPERATP;
|
GVAR(anReserve) = 0 max (GVAR(anReserve) - _anPower / GVAR(anWattsPerATP));
|
||||||
// Increase anearobic fatigue
|
|
||||||
GVAR(anFatigue) = GVAR(anFatigue) + _anPower * (0.057 / GVAR(peakPower)) * 1.1;
|
// Acidosis accumulation
|
||||||
|
GVAR(anFatigue) = GVAR(anFatigue) + _anPower * GVAR(maxPowerFatigueRatio) * 1.1;
|
||||||
|
|
||||||
// Aerobic ATP reserve recovery
|
// Aerobic ATP reserve recovery
|
||||||
GVAR(ae1Reserve) = ((GVAR(ae1Reserve) + _oxygen * 6.60 * (GVAR(ae1PathwayPower) - _ae1Power) / GVAR(ae1PathwayPower) * GVAR(recoveryFactor)) min AE1_MAXRESERVE) max 0;
|
GVAR(ae1Reserve) = (GVAR(ae1Reserve) + _oxygen * GVAR(recoveryFactor) * AE1_ATP_RECOVERY * (GVAR(ae1PathwayPower) - _ae1Power) / GVAR(ae1PathwayPower)) min AE1_MAXRESERVE;
|
||||||
GVAR(ae2Reserve) = ((GVAR(ae2Reserve) + _oxygen * 5.83 * (GVAR(ae2PathwayPower) - _ae2Power) / GVAR(ae2PathwayPower) * GVAR(recoveryFactor)) min AE2_MAXRESERVE) max 0;
|
GVAR(ae2Reserve) = (GVAR(ae2Reserve) + _oxygen * GVAR(recoveryFactor) * AE2_ATP_RECOVERY * (GVAR(ae2PathwayPower) - _ae2Power) / GVAR(ae2PathwayPower)) min AE2_MAXRESERVE;
|
||||||
|
|
||||||
// Anaerobic ATP reserver and fatigue recovery
|
private _aeSurplus = _ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power;
|
||||||
GVAR(anReserve) = ((GVAR(anReserve)
|
|
||||||
+ (_ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power) / GVAR(VO2MaxPower) * 56.7 * GVAR(anFatigue) ^ 2 * GVAR(recoveryFactor)
|
|
||||||
) min AN_MAXRESERVE) max 0;
|
|
||||||
|
|
||||||
GVAR(anFatigue) = ((GVAR(anFatigue)
|
// Anaerobic ATP reserve recovery
|
||||||
- (_ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power) * (0.057 / GVAR(peakPower)) * GVAR(anFatigue) ^ 2 * GVAR(recoveryFactor)
|
GVAR(anReserve) = 0 max (GVAR(anReserve) + _aeSurplus / GVAR(VO2MaxPower) * AN_ATP_RECOVERY * GVAR(recoveryFactor) * (GVAR(anFatigue) max linearConversion [AN_MAXRESERVE, 0, GVAR(anReserve), 0, 0.75, true]) ^ 2) min AN_MAXRESERVE; // max linearConversion ensures that if GVAR(anFatigue) is very low, it will still regenerate reserves
|
||||||
) min 1) max 0;
|
// Acidosis recovery
|
||||||
|
GVAR(anFatigue) = 0 max (GVAR(anFatigue) - _aeSurplus * GVAR(maxPowerFatigueRatio) * GVAR(recoveryFactor) * GVAR(anFatigue) ^ 2) min 1;
|
||||||
|
|
||||||
|
// Respiratory rate decrease
|
||||||
|
GVAR(respiratoryRate) = GVAR(respiratoryRate) * GVAR(respiratoryBufferDivisor);
|
||||||
|
|
||||||
|
// Respiratory rate increase
|
||||||
|
private _aePowerRatio = (GVAR(aePathwayPower) / _aePathwayPowerFatigued) min 2;
|
||||||
|
private _respiratorySampleDivisor = 1 / (RESPIRATORY_BUFFER * 4.72 * GVAR(VO2Max));
|
||||||
|
GVAR(respiratoryRate) = (GVAR(respiratoryRate) + _currentWork * _respiratorySampleDivisor * _aePowerRatio) min 1;
|
||||||
|
|
||||||
|
// Calculate a pseudo-perceived fatigue, which is used for effects
|
||||||
GVAR(aeReservePercentage) = (GVAR(ae1Reserve) / AE1_MAXRESERVE + GVAR(ae2Reserve) / AE2_MAXRESERVE) / 2;
|
GVAR(aeReservePercentage) = (GVAR(ae1Reserve) / AE1_MAXRESERVE + GVAR(ae2Reserve) / AE2_MAXRESERVE) / 2;
|
||||||
GVAR(anReservePercentage) = GVAR(anReserve) / AN_MAXRESERVE;
|
GVAR(anReservePercentage) = GVAR(anReserve) / AN_MAXRESERVE;
|
||||||
private _perceivedFatigue = 1 - (GVAR(anReservePercentage) min GVAR(aeReservePercentage));
|
private _perceivedFatigue = 1 - (GVAR(anReservePercentage) min GVAR(aeReservePercentage));
|
||||||
|
|
||||||
[ACE_player, _perceivedFatigue, _currentSpeed, GVAR(anReserve) == 0] call FUNC(handleEffects);
|
#ifdef DEBUG_MODE_FULL
|
||||||
|
systemChat format ["---- muscleDamage: %1 ----", GVAR(muscleDamage) toFixed 8];
|
||||||
|
systemChat format ["---- ae2: %1 - an: %2 ----", (GVAR(ae2Reserve) / AE2_MAXRESERVE) toFixed 2, (GVAR(anReserve) / AN_MAXRESERVE) toFixed 2];
|
||||||
|
systemChat format ["---- anFatigue: %1 - perceivedFatigue: %2 ----", GVAR(anFatigue) toFixed 2, _perceivedFatigue toFixed 2];
|
||||||
|
systemChat format ["---- velocity %1 - respiratoryRate: %2 ----", (vectorMagnitude _velocity) toFixed 2, GVAR(respiratoryRate) toFixed 2];
|
||||||
|
// systemChat format ["---- aePower: %1 ----", _aePathwayPowerFatigued toFixed 1];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (GVAR(enableStaminaBar)) then {
|
[ACE_player, _perceivedFatigue, GVAR(anReserve) == 0, _fwdAngle, _sideAngle] call FUNC(handleEffects);
|
||||||
|
|
||||||
|
if (GVAR(enableStaminaBarRealized)) then {
|
||||||
[GVAR(anReserve) / AN_MAXRESERVE] call FUNC(handleStaminaBar);
|
[GVAR(anReserve) / AN_MAXRESERVE] call FUNC(handleStaminaBar);
|
||||||
};
|
};
|
||||||
|
|
||||||
[FUNC(mainLoop), [], 1] call CBA_fnc_waitAndExecute;
|
[LINKFUNC(mainLoop), [], 1] call CBA_fnc_waitAndExecute;
|
||||||
|
40
addons/advanced_fatigue/functions/fnc_renderDebugLines.sqf
Normal file
40
addons/advanced_fatigue/functions/fnc_renderDebugLines.sqf
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: ulteq
|
||||||
|
* Draw lines for debugging.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call ace_advanced_fatigue_fnc_renderDebugLines
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
addMissionEventHandler ["Draw3D", {
|
||||||
|
private _normal = surfaceNormal (getPosWorld ACE_player);
|
||||||
|
private _beg = (getPosWorld ACE_player) vectorAdd (_normal vectorMultiply 0.5);
|
||||||
|
private _end = _beg vectorAdd (_normal vectorMultiply 2);
|
||||||
|
drawLine3D [ASLToATL _beg, ASLToATL _end, [0, 1, 0, 1]];
|
||||||
|
|
||||||
|
private _side = vectorNormalized (_normal vectorCrossProduct [0, 0, 1]);
|
||||||
|
private _end = _beg vectorAdd (_side vectorMultiply 2);
|
||||||
|
drawLine3D [ASLToATL _beg, ASLToATL _end, [0, 0, 1, 1]];
|
||||||
|
|
||||||
|
private _up = vectorNormalized (_normal vectorCrossProduct _side);
|
||||||
|
private _end = _beg vectorAdd (_up vectorMultiply 2);
|
||||||
|
drawLine3D [ASLToATL _beg, ASLToATL _end, [1, 0, 0, 1]];
|
||||||
|
|
||||||
|
private _movementVector = vectorNormalized (velocity ACE_player);
|
||||||
|
private _end = _beg vectorAdd (_movementVector vectorMultiply 2);
|
||||||
|
drawLine3D [ASLToATL _beg, ASLToATL _end, [1, 1, 0, 1]];
|
||||||
|
|
||||||
|
private _sideVector = vectorNormalized (_movementVector vectorCrossProduct _normal);
|
||||||
|
_sideVector set [2, 0];
|
||||||
|
private _end = _beg vectorAdd (_sideVector vectorMultiply 2);
|
||||||
|
drawLine3D [ASLToATL _beg, ASLToATL _end, [0, 1, 1, 1]];
|
||||||
|
}];
|
25
addons/advanced_fatigue/functions/fnc_updateStaminaBar.sqf
Normal file
25
addons/advanced_fatigue/functions/fnc_updateStaminaBar.sqf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: PabstMirror
|
||||||
|
* Updates the stamina bar state
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [] call ace_advanced_fatigue_fnc_updateStaminaBar
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
GVAR(enableStaminaBarRealized) = GVAR(enabled) && GVAR(enableStaminaBar) && {!(missionNamespace getVariable [QEGVAR(ui,hideHud), false])};
|
||||||
|
TRACE_1("updateStaminaBar",GVAR(enableStaminaBarRealized));
|
||||||
|
|
||||||
|
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
||||||
|
if (isNull _staminaBarContainer) exitWith {};
|
||||||
|
|
||||||
|
_staminaBarContainer ctrlSetFade ([1, 0] select GVAR(enableStaminaBarRealized));
|
||||||
|
_staminaBarContainer ctrlCommit 0;
|
@ -4,12 +4,9 @@
|
|||||||
[LSTRING(Enabled), LSTRING(Enabled_Description)],
|
[LSTRING(Enabled), LSTRING(Enabled_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
true,
|
true,
|
||||||
true, {
|
1,
|
||||||
if (!_this) then {
|
{
|
||||||
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
call FUNC(updateStaminaBar);
|
||||||
_staminaBarContainer ctrlSetFade 1;
|
|
||||||
_staminaBarContainer ctrlCommit 0;
|
|
||||||
};
|
|
||||||
[QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)
|
[QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)
|
||||||
},
|
},
|
||||||
true // Needs mission restart
|
true // Needs mission restart
|
||||||
@ -21,13 +18,8 @@
|
|||||||
[LSTRING(EnableStaminaBar), LSTRING(EnableStaminaBar_Description)],
|
[LSTRING(EnableStaminaBar), LSTRING(EnableStaminaBar_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
true,
|
true,
|
||||||
true, {
|
1,
|
||||||
if (!_this) then {
|
{call FUNC(updateStaminaBar)}
|
||||||
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
|
||||||
_staminaBarContainer ctrlSetFade 1;
|
|
||||||
_staminaBarContainer ctrlCommit 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -36,7 +28,8 @@
|
|||||||
[LSTRING(FadeStaminaBar), LSTRING(FadeStaminaBar_Description)],
|
[LSTRING(FadeStaminaBar), LSTRING(FadeStaminaBar_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
true,
|
true,
|
||||||
false, {
|
0,
|
||||||
|
{
|
||||||
if (!_this && GVAR(enabled) && GVAR(enableStaminaBar)) then {
|
if (!_this && GVAR(enabled) && GVAR(enableStaminaBar)) then {
|
||||||
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
|
||||||
_staminaBarContainer ctrlSetFade 0;
|
_staminaBarContainer ctrlSetFade 0;
|
||||||
@ -50,8 +43,14 @@
|
|||||||
"SLIDER",
|
"SLIDER",
|
||||||
[LSTRING(PerformanceFactor), LSTRING(PerformanceFactor_Description)],
|
[LSTRING(PerformanceFactor), LSTRING(PerformanceFactor_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
[0, 5, 1, 1],
|
[0, 10, 1, 2],
|
||||||
true
|
1,
|
||||||
|
{
|
||||||
|
// Recalculate values if the setting is changed mid-mission
|
||||||
|
if (GVAR(enabled) && hasInterface && !isNull ACE_player) then {
|
||||||
|
[ACE_player, ACE_player] call FUNC(handlePlayerChanged);
|
||||||
|
};
|
||||||
|
}
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -59,8 +58,8 @@
|
|||||||
"SLIDER",
|
"SLIDER",
|
||||||
[LSTRING(RecoveryFactor), LSTRING(RecoveryFactor_Description)],
|
[LSTRING(RecoveryFactor), LSTRING(RecoveryFactor_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
[0, 5, 1, 1],
|
[0, 10, 1, 2],
|
||||||
true
|
1
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -68,8 +67,8 @@
|
|||||||
"SLIDER",
|
"SLIDER",
|
||||||
[LSTRING(LoadFactor), LSTRING(LoadFactor_Description)],
|
[LSTRING(LoadFactor), LSTRING(LoadFactor_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
[0, 5, 1, 1],
|
[0, 5, 1, 2],
|
||||||
true
|
1
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -77,6 +76,6 @@
|
|||||||
"SLIDER",
|
"SLIDER",
|
||||||
[LSTRING(TerrainGradientFactor), LSTRING(TerrainGradientFactor_Description)],
|
[LSTRING(TerrainGradientFactor), LSTRING(TerrainGradientFactor_Description)],
|
||||||
LSTRING(DisplayName),
|
LSTRING(DisplayName),
|
||||||
[0, 5, 1, 1],
|
[0, 5, 1, 2],
|
||||||
true
|
1
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
@ -16,14 +16,28 @@
|
|||||||
|
|
||||||
#include "\z\ace\addons\main\script_macros.hpp"
|
#include "\z\ace\addons\main\script_macros.hpp"
|
||||||
|
|
||||||
|
#define UNDERWEAR_WEIGHT 3.5
|
||||||
|
|
||||||
#define ANTPERCENT 0.8
|
#define ANTPERCENT 0.8
|
||||||
#define SIM_BODYMASS 70
|
#define SIM_BODYMASS 70
|
||||||
#define JOULES_PER_ML_O2 20.9
|
#define JOULES_PER_ML_O2 20.9
|
||||||
#define VO2MAX_STRENGTH 4.1
|
#define VO2MAX_STRENGTH 4.1
|
||||||
#define REE 18.83 //((0.5617 * SIM_BODYMASS + 42.57) * 0.23)
|
#define BIOMECH_EFFICIENCY 0.23
|
||||||
#define OXYGEN 0.9
|
#define REE 18.83 // ((0.5617 * SIM_BODYMASS + 42.57) * BIOMECH_EFFICIENCY)
|
||||||
#define WATTSPERATP 7
|
|
||||||
|
|
||||||
#define AE1_MAXRESERVE 4000000
|
#define RESPIRATORY_BUFFER 60
|
||||||
#define AE2_MAXRESERVE 84000
|
|
||||||
#define AN_MAXRESERVE 2300
|
#define MUSCLE_TEAR_RATE 0.00004
|
||||||
|
#define MUSCLE_RECOVERY 0.00000386
|
||||||
|
|
||||||
|
#define AE1_ATP_RELEASE_RATE 13.3 // mmol
|
||||||
|
#define AE2_ATP_RELEASE_RATE 16.7 // mmol
|
||||||
|
#define AN_ATP_RELEASE_RATE 113.3 // mmol
|
||||||
|
|
||||||
|
#define AE1_ATP_RECOVERY 6.60 // mmol
|
||||||
|
#define AE2_ATP_RECOVERY 5.83 // mmol
|
||||||
|
#define AN_ATP_RECOVERY 56.70 // mmol
|
||||||
|
|
||||||
|
#define AE1_MAXRESERVE 4000000 // mmol
|
||||||
|
#define AE2_MAXRESERVE 84000 // mmol
|
||||||
|
#define AN_MAXRESERVE 2300 // mmol
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<German>ACE Erweiterte Ausdauer</German>
|
<German>ACE Erweiterte Ausdauer</German>
|
||||||
<Chinese>ACE 進階疲勞</Chinese>
|
<Chinese>ACE 進階疲勞</Chinese>
|
||||||
<Chinesesimp>ACE 进阶体力</Chinesesimp>
|
<Chinesesimp>ACE 进阶体力</Chinesesimp>
|
||||||
<Japanese>ACE アドバンスド疲労</Japanese>
|
<Japanese>ACE 高度な疲労</Japanese>
|
||||||
<Italian>ACE Fatica Avanzata</Italian>
|
<Italian>ACE Fatica Avanzata</Italian>
|
||||||
<Korean>ACE 고급 피로도</Korean>
|
<Korean>ACE 고급 피로도</Korean>
|
||||||
<French>ACE Fatigue avancée</French>
|
<French>ACE Fatigue avancée</French>
|
||||||
@ -173,7 +173,7 @@
|
|||||||
<English>Enables/disables Advanced Fatigue.</English>
|
<English>Enables/disables Advanced Fatigue.</English>
|
||||||
<Spanish>Activa/desactiva la fatiga avanzada</Spanish>
|
<Spanish>Activa/desactiva la fatiga avanzada</Spanish>
|
||||||
<German>Aktiviert/deaktiviert Advanced Fatigue.</German>
|
<German>Aktiviert/deaktiviert Advanced Fatigue.</German>
|
||||||
<Japanese>アドバンスド疲労は高度な疲労管理システムを有効化します。</Japanese>
|
<Japanese>高度な疲労を有効/無効化します。</Japanese>
|
||||||
<Polish>Włącza/wyłącza zaawansowaną wytrzymałość</Polish>
|
<Polish>Włącza/wyłącza zaawansowaną wytrzymałość</Polish>
|
||||||
<Korean>고급 피로도 활성화/비활성화</Korean>
|
<Korean>고급 피로도 활성화/비활성화</Korean>
|
||||||
<French>Active/Désactive la fatigue avancée.</French>
|
<French>Active/Désactive la fatigue avancée.</French>
|
||||||
|
@ -10,20 +10,10 @@ if (!hasInterface) exitWith {};
|
|||||||
// Temporary Wind Info indication
|
// Temporary Wind Info indication
|
||||||
GVAR(tempWindInfo) = false;
|
GVAR(tempWindInfo) = false;
|
||||||
|
|
||||||
// Ammo/Magazines look-up hash for correctness of initSpeed
|
|
||||||
GVAR(ammoMagLookup) = call CBA_fnc_createNamespace;
|
|
||||||
{
|
|
||||||
{
|
|
||||||
private _ammo = getText (configFile >> "CfgMagazines" >> _x >> "ammo");
|
|
||||||
if (_ammo != "") then { GVAR(ammoMagLookup) setVariable [_ammo, _x]; };
|
|
||||||
} forEach (getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines"));
|
|
||||||
} forEach getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles");
|
|
||||||
|
|
||||||
|
|
||||||
// Add keybinds
|
// Add keybinds
|
||||||
["ACE3 Weapons", QGVAR(prepare), localize LSTRING(Prepare), {
|
["ACE3 Weapons", QGVAR(prepare), localize LSTRING(Prepare), {
|
||||||
// Condition
|
// Condition
|
||||||
if (!([ACE_player] call FUNC(canPrepare))) exitWith {false};
|
if !([ACE_player] call FUNC(canPrepare)) exitWith {false};
|
||||||
if (EGVAR(common,isReloading)) exitWith {true};
|
if (EGVAR(common,isReloading)) exitWith {true};
|
||||||
|
|
||||||
// Statement
|
// Statement
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
#include "XEH_PREP.hpp"
|
#include "XEH_PREP.hpp"
|
||||||
|
|
||||||
|
// Ammo/Magazines look-up hash for correctness of initSpeed
|
||||||
|
private _cfgMagazines = configFile >> "CfgMagazines";
|
||||||
|
private _cfgAmmo = configFile >> "CfgAmmo";
|
||||||
|
private _cfgThrow = configFile >> "CfgWeapons" >> "Throw";
|
||||||
|
|
||||||
|
private _ammoMagLookup = createHashMap;
|
||||||
|
|
||||||
|
{
|
||||||
|
{
|
||||||
|
private _ammo = getText (_cfgMagazines >> _x >> "ammo");
|
||||||
|
if (_ammo != "") then {
|
||||||
|
_ammoMagLookup set [configName (_cfgAmmo >> _ammo), _x];
|
||||||
|
};
|
||||||
|
} forEach (getArray (_cfgThrow >> _x >> "magazines"));
|
||||||
|
} forEach (getArray (_cfgThrow >> "muzzles"));
|
||||||
|
|
||||||
|
uiNamespace setVariable [QGVAR(ammoMagLookup), compileFinal _ammoMagLookup];
|
||||||
|
@ -43,13 +43,10 @@ if ((!_primed) && {!((_throwableMag in (uniformItems ACE_player)) || {_throwable
|
|||||||
|
|
||||||
// Get correct throw power for primed grenade
|
// Get correct throw power for primed grenade
|
||||||
if (_primed) then {
|
if (_primed) then {
|
||||||
private _ammoType = typeOf _activeThrowable;
|
// If ammo type is not found:
|
||||||
_throwableMag = GVAR(ammoMagLookup) getVariable _ammoType;
|
// What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke)
|
||||||
if (isNil "_throwableMag") then {
|
// Just use HandGrenade as it has an average initSpeed value
|
||||||
// What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke)
|
_throwableMag = (uiNamespace getVariable QGVAR(ammoMagLookup)) getOrDefault [typeOf _activeThrowable, "HandGrenade"];
|
||||||
// Just use HandGrenade as it has an average initSpeed value
|
|
||||||
_throwableMag = "HandGrenade";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some throwables have different classname for magazine and ammo
|
// Some throwables have different classname for magazine and ammo
|
||||||
|
@ -18,19 +18,10 @@
|
|||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
TRACE_1("params",_unit);
|
TRACE_1("params",_unit);
|
||||||
|
|
||||||
// Temporarily enable wind info, to aid in throwing smoke grenades effectively
|
|
||||||
if (
|
|
||||||
GVAR(enableTempWindInfo) &&
|
|
||||||
{!(missionNamespace getVariable [QEGVAR(weather,WindInfo), false])}
|
|
||||||
) then {
|
|
||||||
[] call EFUNC(weather,displayWindInfo);
|
|
||||||
GVAR(tempWindInfo) = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Select next throwable if one already in hand
|
// Select next throwable if one already in hand
|
||||||
if (_unit getVariable [QGVAR(inHand), false]) exitWith {
|
if (_unit getVariable [QGVAR(inHand), false]) exitWith {
|
||||||
TRACE_1("inHand",_unit);
|
TRACE_1("inHand",_unit);
|
||||||
if (!(_unit getVariable [QGVAR(primed), false])) then {
|
if !(_unit getVariable [QGVAR(primed), false]) then {
|
||||||
TRACE_1("not primed",_unit);
|
TRACE_1("not primed",_unit);
|
||||||
// Restore muzzle ammo (setAmmo 1 has no impact if no appliccable throwable in inventory)
|
// Restore muzzle ammo (setAmmo 1 has no impact if no appliccable throwable in inventory)
|
||||||
// selectNextGrenade relies on muzzles array (setAmmo 0 removes the muzzle from the array and current can't be found, cycles between 0 and 1 muzzles)
|
// selectNextGrenade relies on muzzles array (setAmmo 0 removes the muzzle from the array and current can't be found, cycles between 0 and 1 muzzles)
|
||||||
@ -44,6 +35,11 @@ if (isNull (_unit getVariable [QGVAR(activeThrowable), objNull]) && {(currentThr
|
|||||||
TRACE_1("no throwables",_unit);
|
TRACE_1("no throwables",_unit);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Temporarily enable wind info, to aid in throwing smoke grenades effectively
|
||||||
|
if (GVAR(enableTempWindInfo) && {!(missionNamespace getVariable [QEGVAR(weather,WindInfo), false])}) then {
|
||||||
|
[] call EFUNC(weather,displayWindInfo);
|
||||||
|
GVAR(tempWindInfo) = true;
|
||||||
|
};
|
||||||
|
|
||||||
_unit setVariable [QGVAR(inHand), true];
|
_unit setVariable [QGVAR(inHand), true];
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ TRACE_1("params",_unit);
|
|||||||
|
|
||||||
// Prime the throwable if it hasn't been cooking already
|
// Prime the throwable if it hasn't been cooking already
|
||||||
// Next to proper simulation this also has to happen before delay for orientation of the throwable to be set
|
// Next to proper simulation this also has to happen before delay for orientation of the throwable to be set
|
||||||
if (!(_unit getVariable [QGVAR(primed), false])) then {
|
if !(_unit getVariable [QGVAR(primed), false]) then {
|
||||||
[_unit] call FUNC(prime);
|
[_unit] call FUNC(prime);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<English>Advanced Throwing</English>
|
<English>Advanced Throwing</English>
|
||||||
<Spanish>Lanzamiento Avanzado</Spanish>
|
<Spanish>Lanzamiento Avanzado</Spanish>
|
||||||
<Russian>Улучшенный бросок гранат</Russian>
|
<Russian>Улучшенный бросок гранат</Russian>
|
||||||
<Japanese>アドバンスド投擲</Japanese>
|
<Japanese>高度な投擲</Japanese>
|
||||||
<Polish>Zaawansowane rzucanie</Polish>
|
<Polish>Zaawansowane rzucanie</Polish>
|
||||||
<German>Erweitertes Wurfsystem</German>
|
<German>Erweitertes Wurfsystem</German>
|
||||||
<Korean>고급 투척</Korean>
|
<Korean>고급 투척</Korean>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<English>Allows changing advanced throwing behaviour.</English>
|
<English>Allows changing advanced throwing behaviour.</English>
|
||||||
<Spanish>Permite modificar el comportamiento del lanzamiento avanzado</Spanish>
|
<Spanish>Permite modificar el comportamiento del lanzamiento avanzado</Spanish>
|
||||||
<Russian>Позволяет настраивать поведение улучшенного броска гранат.</Russian>
|
<Russian>Позволяет настраивать поведение улучшенного броска гранат.</Russian>
|
||||||
<Japanese>アドバンスド投擲は投擲の高度な動作挙動を変更可能にします。</Japanese>
|
<Japanese>高度な投擲挙動への変更を可能にします。</Japanese>
|
||||||
<Polish>Zezwala na zmianę zachowania zaawansowanego trybu rzucania.</Polish>
|
<Polish>Zezwala na zmianę zachowania zaawansowanego trybu rzucania.</Polish>
|
||||||
<German>Erlaubt es, das Verhalten des erweiterten Wurfsystems zu ändern.</German>
|
<German>Erlaubt es, das Verhalten des erweiterten Wurfsystems zu ändern.</German>
|
||||||
<Korean>고급 투척 행위를 허가합니다</Korean>
|
<Korean>고급 투척 행위를 허가합니다</Korean>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<English>Enable Advanced Throwing</English>
|
<English>Enable Advanced Throwing</English>
|
||||||
<Spanish>Activar Lanzamiento Avanzado</Spanish>
|
<Spanish>Activar Lanzamiento Avanzado</Spanish>
|
||||||
<Russian>Вкл. улучшенный бросок</Russian>
|
<Russian>Вкл. улучшенный бросок</Russian>
|
||||||
<Japanese>アドバンスド投擲を有効化</Japanese>
|
<Japanese>高度な投擲を有効化</Japanese>
|
||||||
<Polish>Aktywuj zaawansowane rzucanie</Polish>
|
<Polish>Aktywuj zaawansowane rzucanie</Polish>
|
||||||
<German>Aktiviere erweitertes Wurfsystem</German>
|
<German>Aktiviere erweitertes Wurfsystem</German>
|
||||||
<Korean>고급 투척 활성화 </Korean>
|
<Korean>고급 투척 활성화 </Korean>
|
||||||
@ -52,7 +52,7 @@
|
|||||||
<English>Enables advanced throwing system.</English>
|
<English>Enables advanced throwing system.</English>
|
||||||
<Spanish>Activa el Lanzamiento Avanzado</Spanish>
|
<Spanish>Activa el Lanzamiento Avanzado</Spanish>
|
||||||
<Russian>Включает систему улучшенного броска.</Russian>
|
<Russian>Включает систему улучшенного броска.</Russian>
|
||||||
<Japanese>アドバンスド投擲は高度な投擲システムを有効化します。</Japanese>
|
<Japanese>高度な投擲システムを有効化します。</Japanese>
|
||||||
<Polish>Aktywuje system zaawansowanego rzucania.</Polish>
|
<Polish>Aktywuje system zaawansowanego rzucania.</Polish>
|
||||||
<German>Aktiviert das erweiterte Wurfsystem.</German>
|
<German>Aktiviert das erweiterte Wurfsystem.</German>
|
||||||
<Korean>고급 투척을 활성화 합니다</Korean>
|
<Korean>고급 투척을 활성화 합니다</Korean>
|
||||||
@ -144,7 +144,7 @@
|
|||||||
<English>Enables ability to pick up throwables from the ground.</English>
|
<English>Enables ability to pick up throwables from the ground.</English>
|
||||||
<Spanish>Activa la habilidad de coger objetos lanzados del suelo</Spanish>
|
<Spanish>Activa la habilidad de coger objetos lanzados del suelo</Spanish>
|
||||||
<Russian>Включает возможность подбирать гранаты с земли.</Russian>
|
<Russian>Включает возможность подбирать гранаты с земли.</Russian>
|
||||||
<Japanese>地面に落ちている投擲物を拾い上げる機能を有効化します。</Japanese>
|
<Japanese>地面に落ちている投擲物を拾う機能を有効化します。</Japanese>
|
||||||
<Polish>Umożliwia podnoszenie obiektów miotanych z ziemi.</Polish>
|
<Polish>Umożliwia podnoszenie obiektów miotanych z ziemi.</Polish>
|
||||||
<German>Aktiviert die Möglichkeit, geworfene Objekte wieder vom Boden aufzuheben.</German>
|
<German>Aktiviert die Möglichkeit, geworfene Objekte wieder vom Boden aufzuheben.</German>
|
||||||
<Korean>땅에 떨어진 투척물을 주울 수 있게 해줍니다.</Korean>
|
<Korean>땅에 떨어진 투척물을 주울 수 있게 해줍니다.</Korean>
|
||||||
@ -174,7 +174,7 @@
|
|||||||
<English>Enables ability to pick up throwables from attached objects.</English>
|
<English>Enables ability to pick up throwables from attached objects.</English>
|
||||||
<Spanish>Activa la habilidad de lanzar objetos enganchados</Spanish>
|
<Spanish>Activa la habilidad de lanzar objetos enganchados</Spanish>
|
||||||
<Russian>Включает возможность подбирать гранаты, прикрепленные к объектам.</Russian>
|
<Russian>Включает возможность подбирать гранаты, прикрепленные к объектам.</Russian>
|
||||||
<Japanese>オブジェクトに装着された投擲可能物を拾い上げる機能を有効化します。</Japanese>
|
<Japanese>オブジェクトに装着された投擲物を拾う機能を有効化します。</Japanese>
|
||||||
<Polish>Umożliwia podnoszenie obiektów miotanych przyczepionych do innych obiektów.</Polish>
|
<Polish>Umożliwia podnoszenie obiektów miotanych przyczepionych do innych obiektów.</Polish>
|
||||||
<German>Aktiviert die Möglichkeit, befestigte Wurfobjekte erneut aufzunehmen.</German>
|
<German>Aktiviert die Möglichkeit, befestigte Wurfobjekte erneut aufzunehmen.</German>
|
||||||
<Korean>부착된 투척물을 주울 수 있게 해줍니다.</Korean>
|
<Korean>부착된 투척물을 주울 수 있게 해줍니다.</Korean>
|
||||||
@ -192,6 +192,8 @@
|
|||||||
<Japanese>一時的に風の情報を表示</Japanese>
|
<Japanese>一時的に風の情報を表示</Japanese>
|
||||||
<Korean>바람 정보 임시로 표시</Korean>
|
<Korean>바람 정보 임시로 표시</Korean>
|
||||||
<French>Afficher temporairement les informations sur le vent</French>
|
<French>Afficher temporairement les informations sur le vent</French>
|
||||||
|
<Russian>Временно показать информацию о ветре</Russian>
|
||||||
|
<Spanish>Mostrar información del viento temporalmente</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Advanced_Throwing_EnableTempWindInfo_Description">
|
<Key ID="STR_ACE_Advanced_Throwing_EnableTempWindInfo_Description">
|
||||||
<English>Temporarily display Wind Info while throwing, to aid in placing smoke grenades effectively.</English>
|
<English>Temporarily display Wind Info while throwing, to aid in placing smoke grenades effectively.</English>
|
||||||
@ -200,6 +202,8 @@
|
|||||||
<Japanese>投擲行動中に風向きの情報を一時的に表示し、発煙手榴弾の煙幕を効果的に展開しやすくします。</Japanese>
|
<Japanese>投擲行動中に風向きの情報を一時的に表示し、発煙手榴弾の煙幕を効果的に展開しやすくします。</Japanese>
|
||||||
<Korean>연막탄을 효과적으로 배치하는 데 도움이 되도록 투척하는 동안 일시적으로 바람 정보를 표시합니다.</Korean>
|
<Korean>연막탄을 효과적으로 배치하는 데 도움이 되도록 투척하는 동안 일시적으로 바람 정보를 표시합니다.</Korean>
|
||||||
<French>Affiche les informations sur le vent pendant le lancement pour placer les grenades fumigènes plus efficacement.</French>
|
<French>Affiche les informations sur le vent pendant le lancement pour placer les grenades fumigènes plus efficacement.</French>
|
||||||
|
<Russian>Временно отображайте информацию о ветре во время броска, чтобы помочь эффективно разместить дымовые шашки.</Russian>
|
||||||
|
<Spanish>Mostrar información del viento temporalmente mientras se lanza, para ayudar a lanzar las granadas de humo de forma efectiva.</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Advanced_Throwing_Prepare">
|
<Key ID="STR_ACE_Advanced_Throwing_Prepare">
|
||||||
<English>Prepare/Change Throwable</English>
|
<English>Prepare/Change Throwable</English>
|
||||||
@ -250,7 +254,7 @@
|
|||||||
<English>Primed</English>
|
<English>Primed</English>
|
||||||
<Spanish>Preparado</Spanish>
|
<Spanish>Preparado</Spanish>
|
||||||
<Russian>Подготовлена</Russian>
|
<Russian>Подготовлена</Russian>
|
||||||
<Japanese>点火</Japanese>
|
<Japanese>を点火した</Japanese>
|
||||||
<Polish>Odbezpieczony</Polish>
|
<Polish>Odbezpieczony</Polish>
|
||||||
<German>Scharf gemacht</German>
|
<German>Scharf gemacht</German>
|
||||||
<Korean>뇌관 작동</Korean>
|
<Korean>뇌관 작동</Korean>
|
||||||
|
@ -91,6 +91,7 @@
|
|||||||
<Portuguese>Equipar NVGs automaticamente</Portuguese>
|
<Portuguese>Equipar NVGs automaticamente</Portuguese>
|
||||||
<Japanese>暗視装置の自動装備</Japanese>
|
<Japanese>暗視装置の自動装備</Japanese>
|
||||||
<Russian>Автоматическое оснащение ПНВ</Russian>
|
<Russian>Автоматическое оснащение ПНВ</Russian>
|
||||||
|
<Spanish>Auto equipar gafas de visión nocturna</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_AI_AssignNVG_Description">
|
<Key ID="STR_ACE_AI_AssignNVG_Description">
|
||||||
<English>Equips NVG in inventory during night time and unequips it during day time.\nDoes not add NVGs to inventory!</English>
|
<English>Equips NVG in inventory during night time and unequips it during day time.\nDoes not add NVGs to inventory!</English>
|
||||||
@ -102,6 +103,7 @@
|
|||||||
<Portuguese>Equipa o NVG do inventário durante a noite e desequipa durante o dia.\nNão adiciona NVGs ao inventário!</Portuguese>
|
<Portuguese>Equipa o NVG do inventário durante a noite e desequipa durante o dia.\nNão adiciona NVGs ao inventário!</Portuguese>
|
||||||
<Japanese>インベントリ内の暗視装置を夜間に装備し、日中は解除し収納します。\nこれはNVGをインベントリに追加しません。</Japanese>
|
<Japanese>インベントリ内の暗視装置を夜間に装備し、日中は解除し収納します。\nこれはNVGをインベントリに追加しません。</Japanese>
|
||||||
<Russian>Экипирует ПНВ в ночное время и отключает его в дневное время.\nНе добавляет ПНВ в инвентарь!</Russian>
|
<Russian>Экипирует ПНВ в ночное время и отключает его в дневное время.\nНе добавляет ПНВ в инвентарь!</Russian>
|
||||||
|
<Spanish>Equipa las gafas de visión nocturna en el inventario cuando es de noche, y las desequipa cuando es de día.\nNo añade las gafas al inventario!</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
</Package>
|
</Package>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -22,7 +22,7 @@ if (!alive _vehicle) exitWith {};
|
|||||||
if (_vehicle getVariable [QGVAR(droneActionsAdded), false]) exitWith {};
|
if (_vehicle getVariable [QGVAR(droneActionsAdded), false]) exitWith {};
|
||||||
_vehicle setVariable [QGVAR(droneActionsAdded), true];
|
_vehicle setVariable [QGVAR(droneActionsAdded), true];
|
||||||
|
|
||||||
// move to location
|
// Move to location
|
||||||
private _condition = {
|
private _condition = {
|
||||||
params ["_vehicle"];
|
params ["_vehicle"];
|
||||||
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
|
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
|
||||||
@ -37,14 +37,63 @@ private _action = [QGVAR(droneSetWaypointMove), localize "$STR_AC_MOVE",
|
|||||||
"\a3\3DEN\Data\CfgWaypoints\Move_ca.paa", _statement, _condition] call EFUNC(interact_menu,createAction);
|
"\a3\3DEN\Data\CfgWaypoints\Move_ca.paa", _statement, _condition] call EFUNC(interact_menu,createAction);
|
||||||
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
|
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
|
||||||
|
|
||||||
|
// Follow unit/vehicle at turret location
|
||||||
|
_condition = {
|
||||||
|
params ["_vehicle"];
|
||||||
|
private _target = cursorTarget;
|
||||||
|
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]} && {!isNull _target} && {["CAManBase", "LandVehicle", "Ship"] findIf {_target isKindOf _x} != -1}
|
||||||
|
};
|
||||||
|
_statement = {
|
||||||
|
params ["_vehicle"];
|
||||||
|
private _group = group driver _vehicle;
|
||||||
|
private _pos = ([_vehicle, [0]] call FUNC(droneGetTurretTargetPos)) select 0;
|
||||||
|
[QGVAR(droneSetWaypoint), [_vehicle, _group, _pos, "FOLLOW", cursorTarget], _group] call CBA_fnc_targetEvent;
|
||||||
|
private _followDistance = _vehicle getVariable [QGVAR(wpFollowDistance), 0];
|
||||||
|
[[LLSTRING(DroneFollowHint), _followDistance], 3] call EFUNC(common,displayTextStructured);
|
||||||
|
};
|
||||||
|
_action = [QGVAR(droneSetWaypointFollow), localize "$STR_AC_FOLLOW", "\a3\3DEN\Data\CfgWaypoints\Follow_ca.paa", _statement, _condition] call EFUNC(interact_menu,createAction);
|
||||||
|
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
|
||||||
|
|
||||||
|
// Set drone follow distance
|
||||||
|
_condition = {
|
||||||
|
params ["_vehicle"];
|
||||||
|
private _group = group driver _vehicle;
|
||||||
|
private _index = (currentWaypoint _group) min count waypoints _group;
|
||||||
|
private _waypoint = [_group, _index];
|
||||||
|
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]} && {(waypointType _waypoint) == "HOLD"}
|
||||||
|
};
|
||||||
|
_statement = {
|
||||||
|
params ["_vehicle", "", "_value"];
|
||||||
|
_vehicle setVariable [QGVAR(wpFollowDistance), _value];
|
||||||
|
[[LLSTRING(DroneFollowHint), _value], 3] call EFUNC(common,displayTextStructured);
|
||||||
|
};
|
||||||
|
_action = [QGVAR(droneSetFollowDistance), LLSTRING(DroneFollowDistance), "", {}, _condition] call EFUNC(interact_menu,createAction);
|
||||||
|
private _base = [_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
|
||||||
|
private _followDistances = if (_vehicle isKindOf "Car_F") then {
|
||||||
|
[0, 25, 50, 100, 200]
|
||||||
|
} else {
|
||||||
|
[0, 100, 200, 300, 400, 500]
|
||||||
|
};
|
||||||
|
{
|
||||||
|
_action = [
|
||||||
|
QGVAR(droneSetFollowDistance_) + str _x,
|
||||||
|
str _x,
|
||||||
|
"",
|
||||||
|
_statement,
|
||||||
|
{true},
|
||||||
|
{},
|
||||||
|
_x
|
||||||
|
] call EFUNC(interact_menu,createAction);
|
||||||
|
[_vehicle, 1, _base, _action] call EFUNC(interact_menu,addActionToObject);
|
||||||
|
} forEach _followDistances;
|
||||||
|
|
||||||
if (_vehicle isKindOf "Air") then {
|
if (_vehicle isKindOf "Air") then {
|
||||||
// loiter at location
|
// Loiter at location
|
||||||
_condition = {
|
_condition = {
|
||||||
params ["_vehicle"];
|
params ["_vehicle"];
|
||||||
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
|
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
|
||||||
};
|
};
|
||||||
_statement = {
|
_statement = {
|
||||||
params ["_vehicle"];
|
params ["_vehicle"];
|
||||||
private _group = group driver _vehicle;
|
private _group = group driver _vehicle;
|
||||||
private _pos = ([_vehicle, [0]] call FUNC(droneGetTurretTargetPos)) select 0;
|
private _pos = ([_vehicle, [0]] call FUNC(droneGetTurretTargetPos)) select 0;
|
||||||
@ -55,7 +104,7 @@ if (_vehicle isKindOf "Air") then {
|
|||||||
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
|
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
|
||||||
|
|
||||||
|
|
||||||
// set height
|
// Set height
|
||||||
_condition = {
|
_condition = {
|
||||||
params ["_vehicle"];
|
params ["_vehicle"];
|
||||||
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
|
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
|
||||||
@ -74,7 +123,7 @@ if (_vehicle isKindOf "Air") then {
|
|||||||
} forEach [20, 50, 200, 500, 2000];
|
} forEach [20, 50, 200, 500, 2000];
|
||||||
|
|
||||||
|
|
||||||
// set loiter radius
|
// Set loiter radius
|
||||||
_condition = {
|
_condition = {
|
||||||
params ["_vehicle"];
|
params ["_vehicle"];
|
||||||
private _group = group driver _vehicle;
|
private _group = group driver _vehicle;
|
||||||
@ -97,7 +146,7 @@ if (_vehicle isKindOf "Air") then {
|
|||||||
} forEach [500, 750, 1000, 1250, 1500];
|
} forEach [500, 750, 1000, 1250, 1500];
|
||||||
|
|
||||||
|
|
||||||
// set loiter direction
|
// Set loiter direction
|
||||||
_condition = {
|
_condition = {
|
||||||
params ["_vehicle", "", "_args"];
|
params ["_vehicle", "", "_args"];
|
||||||
private _group = group driver _vehicle;
|
private _group = group driver _vehicle;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
* 1: Group <GROUP>
|
* 1: Group <GROUP>
|
||||||
* 2: Pos 2D <ARRAY>
|
* 2: Pos 2D <ARRAY>
|
||||||
* 3: Type <STRING>
|
* 3: Type <STRING>
|
||||||
|
* 4: Target to follow <OBJECT> (default: objNull)
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* None
|
* None
|
||||||
@ -18,7 +19,7 @@
|
|||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
params ["_vehicle", "_group", "_pos", "_type"];
|
params ["_vehicle", "_group", "_pos", "_type", ["_target", objNull]];
|
||||||
TRACE_4("droneSetWaypoint",_vehicle,_group,_pos,_type);
|
TRACE_4("droneSetWaypoint",_vehicle,_group,_pos,_type);
|
||||||
|
|
||||||
private _index = (currentWaypoint _group) min count waypoints _group;
|
private _index = (currentWaypoint _group) min count waypoints _group;
|
||||||
@ -34,9 +35,34 @@ _pos set [
|
|||||||
[0, _currentHeight] select (_currentHeight >= 50)
|
[0, _currentHeight] select (_currentHeight >= 50)
|
||||||
];
|
];
|
||||||
|
|
||||||
// [_group] call CBA_fnc_clearWaypoints;
|
|
||||||
_waypoint = _group addWaypoint [_pos, 0];
|
_waypoint = _group addWaypoint [_pos, 0];
|
||||||
_waypoint setWaypointType _type;
|
// The Vanilla "FOLLOW"-type waypoint is not used directly, due to 2 main issues (as of v2.16):
|
||||||
|
// - It does not work at all for UGVs, which is a known issue https://feedback.bistudio.com/T126283;
|
||||||
|
// - No clear scripting way was found to mimic the UAV Terminal's "Follow Distance" functionality;
|
||||||
|
// Instead, the solution for both UAV and UGV following consists of a CBA PFH that moves a "HOLD"-type Waypoint every 3 seconds.
|
||||||
|
// Either on the target itself, or on the Drone's current position if the target is within the desired follow distance.
|
||||||
|
if (_type == "FOLLOW" && {["CAManBase", "LandVehicle", "Ship"] findIf {_target isKindOf _x} != -1}) then {
|
||||||
|
_waypoint setWaypointType "HOLD";
|
||||||
|
[{
|
||||||
|
params ["_args", "_handle"];
|
||||||
|
_args params ["_vehicle", "_group", "_waypoint", "_target"];
|
||||||
|
|
||||||
|
if ( // Abort PFH if a new waypoint is created via UAV Terminal or ACE Interaction
|
||||||
|
_waypoint select 1 != currentWaypoint _group ||
|
||||||
|
{!alive _vehicle} || {isNull _target}
|
||||||
|
) exitWith {
|
||||||
|
deleteWaypoint _waypoint;
|
||||||
|
[_handle] call CBA_fnc_removePerFrameHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
private _followDistance = _vehicle getVariable [QGVAR(wpFollowDistance), 0];
|
||||||
|
if ((_vehicle distance2D _target) < _followDistance) then {
|
||||||
|
_waypoint setWaypointPosition [getPosASL _vehicle, -1];
|
||||||
|
} else {
|
||||||
|
_waypoint setWaypointPosition [getPosASL _target, -1];
|
||||||
|
};
|
||||||
|
}, 3, [_vehicle, _group, _waypoint, _target]] call CBA_fnc_addPerFrameHandler;
|
||||||
|
};
|
||||||
|
|
||||||
TRACE_3("",_currentHeight,_currentLoiterRadius,_currentLoiterType);
|
TRACE_3("",_currentHeight,_currentLoiterRadius,_currentLoiterType);
|
||||||
if (_currentHeight > 1) then { _vehicle flyInHeight _currentHeight; };
|
if (_currentHeight > 1) then { _vehicle flyInHeight _currentHeight; };
|
||||||
|
@ -129,7 +129,7 @@
|
|||||||
<Japanese>30mm コンバット ミックス 4:1 劣化ウラン徹甲弾:焼夷榴弾</Japanese>
|
<Japanese>30mm コンバット ミックス 4:1 劣化ウラン徹甲弾:焼夷榴弾</Japanese>
|
||||||
<Czech>30mm Bojový Mix 4:1 DU:HEI</Czech>
|
<Czech>30mm Bojový Mix 4:1 DU:HEI</Czech>
|
||||||
<Russian>30мм Смешанное боепитание 4:1 ОУ:ОФЗ</Russian>
|
<Russian>30мм Смешанное боепитание 4:1 ОУ:ОФЗ</Russian>
|
||||||
<Korean>30mm 4:1 열화:고폭소이</Korean>
|
<Korean>30mm 열화우라늄:고폭소이 4:1 혼합</Korean>
|
||||||
<Portuguese>30mm Mix de Combate 4:1 DU:AEI</Portuguese>
|
<Portuguese>30mm Mix de Combate 4:1 DU:AEI</Portuguese>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Aircraft_GatlingDescriptionShortCM41">
|
<Key ID="STR_ACE_Aircraft_GatlingDescriptionShortCM41">
|
||||||
@ -145,7 +145,7 @@
|
|||||||
<Japanese>30mm CM 4:1</Japanese>
|
<Japanese>30mm CM 4:1</Japanese>
|
||||||
<Czech>30mm BM 4:1</Czech>
|
<Czech>30mm BM 4:1</Czech>
|
||||||
<Russian>30мм СБ 4:1</Russian>
|
<Russian>30мм СБ 4:1</Russian>
|
||||||
<Korean>30mm CM 4:1</Korean>
|
<Korean>30mm 4:1 혼합</Korean>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Aircraft_GatlingDescriptionCM51">
|
<Key ID="STR_ACE_Aircraft_GatlingDescriptionCM51">
|
||||||
<English>30mm Combat Mix 5:1 DU:HEI</English>
|
<English>30mm Combat Mix 5:1 DU:HEI</English>
|
||||||
@ -160,7 +160,7 @@
|
|||||||
<Japanese>30mm コンバット ミックス 5:1 劣化ウラン徹甲弾:焼夷榴弾</Japanese>
|
<Japanese>30mm コンバット ミックス 5:1 劣化ウラン徹甲弾:焼夷榴弾</Japanese>
|
||||||
<Czech>30mm Bojový Mix 5:1 DU:HEI</Czech>
|
<Czech>30mm Bojový Mix 5:1 DU:HEI</Czech>
|
||||||
<Russian>30мм Смешанное боепитание 5:1 ОУ:ОФЗ</Russian>
|
<Russian>30мм Смешанное боепитание 5:1 ОУ:ОФЗ</Russian>
|
||||||
<Korean>30mm 5:1 열화:고폭소이</Korean>
|
<Korean>30mm 열화우라늄:고폭소이 5:1 혼합</Korean>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Aircraft_GatlingDescriptionShortCM51">
|
<Key ID="STR_ACE_Aircraft_GatlingDescriptionShortCM51">
|
||||||
<English>30mm CM 5:1</English>
|
<English>30mm CM 5:1</English>
|
||||||
@ -175,7 +175,23 @@
|
|||||||
<Japanese>30mm CM 5:1</Japanese>
|
<Japanese>30mm CM 5:1</Japanese>
|
||||||
<Czech>30mm BM 5:1</Czech>
|
<Czech>30mm BM 5:1</Czech>
|
||||||
<Russian>30мм СБ 5:1</Russian>
|
<Russian>30мм СБ 5:1</Russian>
|
||||||
<Korean>30mm CM 5:1</Korean>
|
<Korean>30mm 5:1 혼합</Korean>
|
||||||
|
</Key>
|
||||||
|
<Key ID="STR_ACE_Aircraft_DroneFollowDistance">
|
||||||
|
<English>Follow Distance</English>
|
||||||
|
<Italian>Distanza di seguimento</Italian>
|
||||||
|
<German>Folge-Entfernung</German>
|
||||||
|
<Korean>따라가는 거리</Korean>
|
||||||
|
<French>Distance de suivi</French>
|
||||||
|
<Japanese>追跡距離</Japanese>
|
||||||
|
</Key>
|
||||||
|
<Key ID="STR_ACE_Aircraft_DroneFollowHint">
|
||||||
|
<English>Following unit within %1m</English>
|
||||||
|
<Italian>Seguendo unità entro %1m</Italian>
|
||||||
|
<German>Folgt Einheit bis zu %1m</German>
|
||||||
|
<Korean>%1m 이내로 유닛을 따라갑니다</Korean>
|
||||||
|
<French>Suivre l'unité jusqu'à %1m</French>
|
||||||
|
<Japanese>%1m 間隔で 目標を追跡します</Japanese>
|
||||||
</Key>
|
</Key>
|
||||||
</Package>
|
</Package>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -78,6 +78,7 @@ PREP(removeStat);
|
|||||||
PREP(removeVirtualItems);
|
PREP(removeVirtualItems);
|
||||||
PREP(renameDefaultLoadout);
|
PREP(renameDefaultLoadout);
|
||||||
PREP(replaceUniqueItemsLoadout);
|
PREP(replaceUniqueItemsLoadout);
|
||||||
|
PREP(saveLoadout);
|
||||||
PREP(scanConfig);
|
PREP(scanConfig);
|
||||||
PREP(showItem);
|
PREP(showItem);
|
||||||
PREP(sortPanel);
|
PREP(sortPanel);
|
||||||
|
@ -85,10 +85,10 @@ private _insigniaCondition = toString {
|
|||||||
|
|
||||||
// Ref fnc_addListBoxItem, 0/nil = configFile, 1 = campaignConfigFile, 2 = missionConfigFile
|
// Ref fnc_addListBoxItem, 0/nil = configFile, 1 = campaignConfigFile, 2 = missionConfigFile
|
||||||
{
|
{
|
||||||
GVAR(insigniaCache) set [_x, 1];
|
GVAR(insigniaCache) set [configName _x, 1];
|
||||||
} forEach (_insigniaCondition configClasses (campaignConfigFile >> "CfgUnitInsignia"));
|
} forEach (_insigniaCondition configClasses (campaignConfigFile >> "CfgUnitInsignia"));
|
||||||
{
|
{
|
||||||
GVAR(insigniaCache) set [_x, 2];
|
GVAR(insigniaCache) set [configName _x, 2];
|
||||||
} forEach (_insigniaCondition configClasses (missionConfigFile >> "CfgUnitInsignia"));
|
} forEach (_insigniaCondition configClasses (missionConfigFile >> "CfgUnitInsignia"));
|
||||||
|
|
||||||
ADDON = true;
|
ADDON = true;
|
||||||
|
@ -26,28 +26,27 @@ if (GVAR(shiftState)) then {
|
|||||||
switch (true) do {
|
switch (true) do {
|
||||||
// Beginning
|
// Beginning
|
||||||
case (_index == -1): {
|
case (_index == -1): {
|
||||||
"ace_clipboard" callExtension (format ["[%1", endl]);
|
"ace" callExtension ["clipboard:append", [format ["[%1", endl]]];
|
||||||
};
|
};
|
||||||
// End
|
// End
|
||||||
case (_index == _listLength): {
|
case (_index == _listLength): {
|
||||||
"ace_clipboard" callExtension "];";
|
"ace" callExtension ["clipboard:append", ["];"]];
|
||||||
};
|
};
|
||||||
// Rest
|
// Rest
|
||||||
default {
|
default {
|
||||||
"ace_clipboard" callExtension ([" ", str (GVAR(defaultLoadoutsList) select _index), [",", ""] select (_index == _listLength - 1), endl] joinString "");
|
"ace" callExtension ["clipboard:append", [[" ", str (GVAR(defaultLoadoutsList) select _index), [",", ""] select (_index == _listLength - 1), endl] joinString ""]];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
"ace_clipboard" callExtension "--COMPLETE--";
|
"ace" callExtension ["clipboard:complete", []];
|
||||||
|
|
||||||
[_display, LLSTRING(exportDefault)] call FUNC(message);
|
[_display, LLSTRING(exportDefault)] call FUNC(message);
|
||||||
} else {
|
} else {
|
||||||
// Export singular loadout
|
// Export singular loadout
|
||||||
private _export = str (GVAR(center) call CBA_fnc_getLoadout);
|
private _export = str (GVAR(center) call CBA_fnc_getLoadout);
|
||||||
|
"ace" callExtension ["clipboard:append", [_export]];
|
||||||
"ace_clipboard" callExtension (_export + ";");
|
"ace" callExtension ["clipboard:complete", []];
|
||||||
"ace_clipboard" callExtension "--COMPLETE--";
|
|
||||||
|
|
||||||
[_display, LLSTRING(exportCurrent)] call FUNC(message);
|
[_display, LLSTRING(exportCurrent)] call FUNC(message);
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,13 @@
|
|||||||
params ["_display"];
|
params ["_display"];
|
||||||
|
|
||||||
// Can be either a singular loadout or an array of loadouts
|
// Can be either a singular loadout or an array of loadouts
|
||||||
private _extendedLoadout = call compile copyFromClipboard;
|
private _extendedLoadout = if (isMultiplayer) then {
|
||||||
|
("ace" callExtension ["clipboard:loadout", []]) params ["_loadout", "_code"];
|
||||||
|
if (_code != 0) exitWith {};
|
||||||
|
parseSimpleArray _loadout
|
||||||
|
} else {
|
||||||
|
call compile copyFromClipboard
|
||||||
|
};
|
||||||
|
|
||||||
// If error, exit
|
// If error, exit
|
||||||
if (isNil "_extendedLoadout" || {!(_extendedLoadout isEqualType [])}) exitWith {
|
if (isNil "_extendedLoadout" || {!(_extendedLoadout isEqualType [])}) exitWith {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
(_this select 1) params ["", "_exitCode"];
|
(_this select 1) params ["", "_exitCode"];
|
||||||
|
|
||||||
[QGVAR(displayClosed), []] call CBA_fnc_localEvent;
|
[QGVAR(displayClosed), []] call CBA_fnc_localEvent;
|
||||||
removeMissionEventHandler ["draw3D", GVAR(camPosUpdateHandle)];
|
removeMissionEventHandler ["Draw3D", GVAR(camPosUpdateHandle)];
|
||||||
|
|
||||||
if (is3DEN) then {
|
if (is3DEN) then {
|
||||||
private _centerOriginParent = objectParent GVAR(centerOrigin);
|
private _centerOriginParent = objectParent GVAR(centerOrigin);
|
||||||
|
@ -138,14 +138,6 @@ _actionsBoxCtrl ctrlSetPosition [
|
|||||||
];
|
];
|
||||||
_actionsBoxCtrl ctrlCommit 0;
|
_actionsBoxCtrl ctrlCommit 0;
|
||||||
|
|
||||||
// Disable import in MP
|
|
||||||
if (isMultiplayer) then {
|
|
||||||
private _importButtonCtrl = _display displayCtrl IDC_buttonImport;
|
|
||||||
_importButtonCtrl ctrlEnable false;
|
|
||||||
_importButtonCtrl ctrlSetFade 0.6;
|
|
||||||
_importButtonCtrl ctrlCommit 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//--------------- Camera prep
|
//--------------- Camera prep
|
||||||
cutText ["", "PLAIN"];
|
cutText ["", "PLAIN"];
|
||||||
showCommandingMenu "";
|
showCommandingMenu "";
|
||||||
@ -278,4 +270,4 @@ showCinemaBorder false;
|
|||||||
|
|
||||||
//--------------- Reset camera pos
|
//--------------- Reset camera pos
|
||||||
[nil, [controlNull, 0, 0]] call FUNC(handleMouse);
|
[nil, [controlNull, 0, 0]] call FUNC(handleMouse);
|
||||||
GVAR(camPosUpdateHandle) = addMissionEventHandler ["draw3D", {call FUNC(updateCamPos)}];
|
GVAR(camPosUpdateHandle) = addMissionEventHandler ["Draw3D", {call FUNC(updateCamPos)}];
|
||||||
|
@ -94,8 +94,8 @@ if (!isNull _loadoutsDisplay) then {
|
|||||||
};
|
};
|
||||||
} params ["_className"];
|
} params ["_className"];
|
||||||
|
|
||||||
"ace_clipboard" callExtension (_className + ";");
|
"ace" callExtension ["clipboard:append", [_className]];
|
||||||
"ace_clipboard" callExtension "--COMPLETE--";
|
"ace" callExtension ["clipboard:complete", []];
|
||||||
|
|
||||||
[_display, LLSTRING(exportedClassnameText)] call FUNC(message);
|
[_display, LLSTRING(exportedClassnameText)] call FUNC(message);
|
||||||
} else {
|
} else {
|
||||||
|
@ -382,6 +382,9 @@ switch (GVAR(currentLeftPanel)) do {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GVAR(currentItems) set [IDX_CURR_VEST, _item];
|
GVAR(currentItems) set [IDX_CURR_VEST, _item];
|
||||||
|
|
||||||
|
[GVAR(center), ""] call BIS_fnc_setUnitInsignia;
|
||||||
|
[GVAR(center), GVAR(currentInsignia)] call BIS_fnc_setUnitInsignia;
|
||||||
};
|
};
|
||||||
|
|
||||||
TOGGLE_RIGHT_PANEL_CONTAINER
|
TOGGLE_RIGHT_PANEL_CONTAINER
|
||||||
@ -420,6 +423,9 @@ switch (GVAR(currentLeftPanel)) do {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GVAR(currentItems) set [IDX_CURR_BACKPACK, _item];
|
GVAR(currentItems) set [IDX_CURR_BACKPACK, _item];
|
||||||
|
|
||||||
|
[GVAR(center), ""] call BIS_fnc_setUnitInsignia;
|
||||||
|
[GVAR(center), GVAR(currentInsignia)] call BIS_fnc_setUnitInsignia;
|
||||||
};
|
};
|
||||||
|
|
||||||
TOGGLE_RIGHT_PANEL_CONTAINER
|
TOGGLE_RIGHT_PANEL_CONTAINER
|
||||||
|
@ -69,7 +69,14 @@ switch (_currentItemsIndex) do {
|
|||||||
// Secondary weapon
|
// Secondary weapon
|
||||||
case IDX_CURR_SECONDARY_WEAPON_ITEMS: {
|
case IDX_CURR_SECONDARY_WEAPON_ITEMS: {
|
||||||
private _currentItemInSlot = (GVAR(currentItems) select IDX_CURR_SECONDARY_WEAPON_ITEMS) select _itemIndex;
|
private _currentItemInSlot = (GVAR(currentItems) select IDX_CURR_SECONDARY_WEAPON_ITEMS) select _itemIndex;
|
||||||
private _isDisposable = CBA_disposable_replaceDisposableLauncher && {!isNil {CBA_disposable_loadedLaunchers getVariable (secondaryWeapon GVAR(center))}};
|
private _isDisposable = CBA_disposable_replaceDisposableLauncher && {!isNil "CBA_disposable_loadedLaunchers"} &&
|
||||||
|
{
|
||||||
|
if (CBA_disposable_loadedLaunchers isEqualType createHashMap) then { // after CBA 3.18
|
||||||
|
(secondaryWeapon GVAR(center)) in CBA_disposable_loadedLaunchers
|
||||||
|
} else {
|
||||||
|
!isNil {CBA_disposable_loadedLaunchers getVariable (secondaryWeapon player)}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// If removal
|
// If removal
|
||||||
if (_item == "") then {
|
if (_item == "") then {
|
||||||
|
37
addons/arsenal/functions/fnc_saveLoadout.sqf
Normal file
37
addons/arsenal/functions/fnc_saveLoadout.sqf
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: DartRuffian
|
||||||
|
* Saves a given loadout to the client's profile.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Name of loadout <STRING>
|
||||||
|
* 1: CBA extended loadout or getUnitLoadout array <ARRAY>
|
||||||
|
* 2: Replace existing loadout <BOOL> (default: false)
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* True if loadout was saved, otherwise false <BOOL>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ["Current Loadout", getUnitLoadout ACE_player] call ace_arsenal_fnc_saveLoadout
|
||||||
|
*
|
||||||
|
* Public: Yes
|
||||||
|
*/
|
||||||
|
|
||||||
|
params [["_name", "", [""]], ["_loadout", [], [[]]], ["_replaceExisting", false, [false]]];
|
||||||
|
|
||||||
|
if (_name == "" || {_loadout isEqualTo []}) exitWith { false };
|
||||||
|
|
||||||
|
private _loadouts = profileNamespace getVariable [QGVAR(saved_loadouts), []];
|
||||||
|
private _loadoutIndex = _loadouts findIf {(_x#0) == _name};
|
||||||
|
|
||||||
|
// If a loadout with same name already exists and no overwriting enabled, quit
|
||||||
|
if (!_replaceExisting && {_loadoutIndex != -1}) exitWith { false };
|
||||||
|
|
||||||
|
if (_loadoutIndex == -1) then {
|
||||||
|
_loadouts pushBack [_name, _loadout];
|
||||||
|
} else {
|
||||||
|
_loadouts set [_loadoutIndex, [_name, _loadout]];
|
||||||
|
};
|
||||||
|
|
||||||
|
profileNamespace setVariable [QGVAR(saved_loadouts), _loadouts];
|
||||||
|
true
|
@ -72,6 +72,6 @@ if (_nextAction != GVAR(currentAction)) then {
|
|||||||
GVAR(currentAction) = _nextAction;
|
GVAR(currentAction) = _nextAction;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(GVAR(currentAction) in ["Civil", "Salute"])) then {
|
if !(GVAR(currentAction) in ["Civil", "Salute"]) then {
|
||||||
GVAR(center) selectWeapon ([primaryWeapon GVAR(center), secondaryWeapon GVAR(center), handgunWeapon GVAR(center), binocular GVAR(center)] select GVAR(selectedWeaponType)); // select correct weapon, prevents floating weapons
|
GVAR(center) selectWeapon ([primaryWeapon GVAR(center), secondaryWeapon GVAR(center), handgunWeapon GVAR(center), binocular GVAR(center)] select GVAR(selectedWeaponType)); // select correct weapon, prevents floating weapons
|
||||||
};
|
};
|
||||||
|
@ -14,4 +14,9 @@
|
|||||||
|
|
||||||
params ["_config"];
|
params ["_config"];
|
||||||
|
|
||||||
(modParams [_config call EFUNC(common,getAddon), ["name"]]) param [0, ""]
|
private _addon = _config call EFUNC(common,getAddon);
|
||||||
|
|
||||||
|
// Calling modParams with "" prints 'ModParams - Undefined or empty mod directory' in RPT
|
||||||
|
if (_addon == "") exitWith {""};
|
||||||
|
|
||||||
|
(modParams [_addon, ["name"]]) param [0, ""]
|
||||||
|
@ -63,7 +63,7 @@ _target switchMove "amovpercmstpslowwrfldnon";
|
|||||||
_target setVariable ["origin", _position];
|
_target setVariable ["origin", _position];
|
||||||
|
|
||||||
// When killed, respawn AI
|
// When killed, respawn AI
|
||||||
_target addEventHandler ["killed", {
|
_target addEventHandler ["Killed", {
|
||||||
params ["_target"];
|
params ["_target"];
|
||||||
|
|
||||||
// Killed may fire twice, 2nd will be null - https://github.com/acemod/ACE3/pull/7561
|
// Killed may fire twice, 2nd will be null - https://github.com/acemod/ACE3/pull/7561
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<French>Masque l'interface</French>
|
<French>Masque l'interface</French>
|
||||||
<German>Oberfläche verstecken</German>
|
<German>Oberfläche verstecken</German>
|
||||||
<Polish>Ukryj interfejs</Polish>
|
<Polish>Ukryj interfejs</Polish>
|
||||||
<Japanese>インターフェースを隠す</Japanese>
|
<Japanese>インタフェースを隠す</Japanese>
|
||||||
<Italian>Nascondi interfaccia</Italian>
|
<Italian>Nascondi interfaccia</Italian>
|
||||||
<Korean>인터페이스 숨기기</Korean>
|
<Korean>인터페이스 숨기기</Korean>
|
||||||
<Chinese>隱藏介面</Chinese>
|
<Chinese>隱藏介面</Chinese>
|
||||||
@ -1245,6 +1245,8 @@
|
|||||||
<Russian>Интегрирован тепловизор.</Russian>
|
<Russian>Интегрирован тепловизор.</Russian>
|
||||||
<Korean>열화상 내장</Korean>
|
<Korean>열화상 내장</Korean>
|
||||||
<French>Thermique intégrée</French>
|
<French>Thermique intégrée</French>
|
||||||
|
<German>Thermal integriert</German>
|
||||||
|
<Spanish>Térmica integrada</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_statVisionMode_intPrimTi">
|
<Key ID="STR_ACE_Arsenal_statVisionMode_intPrimTi">
|
||||||
<English>Thermal & Primary integrated</English>
|
<English>Thermal & Primary integrated</English>
|
||||||
@ -1253,6 +1255,8 @@
|
|||||||
<Russian>Интегрирован тепловизор и осн.прицел.</Russian>
|
<Russian>Интегрирован тепловизор и осн.прицел.</Russian>
|
||||||
<Korean>열화상과 주무기 내장</Korean>
|
<Korean>열화상과 주무기 내장</Korean>
|
||||||
<French>Thermique et primaire intégrés</French>
|
<French>Thermique et primaire intégrés</French>
|
||||||
|
<German>Thermal und in Primärwaffe integriert</German>
|
||||||
|
<Spanish>Térmica y Primaria integrada</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_statVisionMode_NoSup">
|
<Key ID="STR_ACE_Arsenal_statVisionMode_NoSup">
|
||||||
<English>Not Supported</English>
|
<English>Not Supported</English>
|
||||||
@ -1609,6 +1613,7 @@
|
|||||||
<French>Décroissant</French>
|
<French>Décroissant</French>
|
||||||
<Portuguese>Decrescente</Portuguese>
|
<Portuguese>Decrescente</Portuguese>
|
||||||
<Russian>Нисходящий</Russian>
|
<Russian>Нисходящий</Russian>
|
||||||
|
<Spanish>Descendiente</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_sortAscending">
|
<Key ID="STR_ACE_Arsenal_sortAscending">
|
||||||
<English>Ascending</English>
|
<English>Ascending</English>
|
||||||
@ -1620,6 +1625,7 @@
|
|||||||
<French>Croissant</French>
|
<French>Croissant</French>
|
||||||
<Portuguese>Crescente</Portuguese>
|
<Portuguese>Crescente</Portuguese>
|
||||||
<Russian>Восходящий</Russian>
|
<Russian>Восходящий</Russian>
|
||||||
|
<Spanish>Ascendiente</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_toolsTab">
|
<Key ID="STR_ACE_Arsenal_toolsTab">
|
||||||
<English>Tools</English>
|
<English>Tools</English>
|
||||||
@ -1647,6 +1653,7 @@
|
|||||||
<French>Nombre de munitions</French>
|
<French>Nombre de munitions</French>
|
||||||
<Portuguese>Quantidade de munição</Portuguese>
|
<Portuguese>Quantidade de munição</Portuguese>
|
||||||
<Russian>Количество боеприпасов</Russian>
|
<Russian>Количество боеприпасов</Russian>
|
||||||
|
<Spanish>Cantidad de munición</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_statIlluminators">
|
<Key ID="STR_ACE_Arsenal_statIlluminators">
|
||||||
<English>Illuminators</English>
|
<English>Illuminators</English>
|
||||||
@ -1657,6 +1664,7 @@
|
|||||||
<Portuguese>Iluminadores</Portuguese>
|
<Portuguese>Iluminadores</Portuguese>
|
||||||
<Japanese>イルミネーター</Japanese>
|
<Japanese>イルミネーター</Japanese>
|
||||||
<Russian>Осветители</Russian>
|
<Russian>Осветители</Russian>
|
||||||
|
<Spanish>Iluminadores</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_defaultToFavoritesSetting">
|
<Key ID="STR_ACE_Arsenal_defaultToFavoritesSetting">
|
||||||
<English>Default to Favorites</English>
|
<English>Default to Favorites</English>
|
||||||
@ -1668,6 +1676,7 @@
|
|||||||
<French>Favoris par défaut</French>
|
<French>Favoris par défaut</French>
|
||||||
<Portuguese>Favoritos por padrão</Portuguese>
|
<Portuguese>Favoritos por padrão</Portuguese>
|
||||||
<Russian>По умолчанию - Избранное</Russian>
|
<Russian>По умолчанию - Избранное</Russian>
|
||||||
|
<Spanish>Favoritos por defecto</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_defaultToFavoritesTooltip">
|
<Key ID="STR_ACE_Arsenal_defaultToFavoritesTooltip">
|
||||||
<English>Controls whether the ACE Arsenal defaults to showing all items or favorites.</English>
|
<English>Controls whether the ACE Arsenal defaults to showing all items or favorites.</English>
|
||||||
@ -1679,6 +1688,7 @@
|
|||||||
<French>Contrôle si l'arsenal ACE affiche par défaut tous les éléments ou les favoris.</French>
|
<French>Contrôle si l'arsenal ACE affiche par défaut tous les éléments ou les favoris.</French>
|
||||||
<Portuguese>Controla se o Arsenal ACE exibe por padrão todos os itens ou favoritos.</Portuguese>
|
<Portuguese>Controla se o Arsenal ACE exibe por padrão todos os itens ou favoritos.</Portuguese>
|
||||||
<Russian>Определяет, будет ли в арсенале ACE по умолчанию отображаться все предметы или избранное.</Russian>
|
<Russian>Определяет, будет ли в арсенале ACE по умолчанию отображаться все предметы или избранное.</Russian>
|
||||||
|
<Spanish>Controla si el Arsenal de ACE muestra por defecto todos los objetos o sólo los favoritos</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_favoritesColorSetting">
|
<Key ID="STR_ACE_Arsenal_favoritesColorSetting">
|
||||||
<English>Favorites Color</English>
|
<English>Favorites Color</English>
|
||||||
@ -1690,6 +1700,7 @@
|
|||||||
<French>Couleurs favorites</French>
|
<French>Couleurs favorites</French>
|
||||||
<Portuguese>Cor dos favoritos</Portuguese>
|
<Portuguese>Cor dos favoritos</Portuguese>
|
||||||
<Russian>Избранный цвет</Russian>
|
<Russian>Избранный цвет</Russian>
|
||||||
|
<Spanish>Color de Favoritos</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_favoritesColorTooltip">
|
<Key ID="STR_ACE_Arsenal_favoritesColorTooltip">
|
||||||
<English>Highlight color for favorited items.</English>
|
<English>Highlight color for favorited items.</English>
|
||||||
@ -1701,6 +1712,7 @@
|
|||||||
<French>Met en surbrillance les éléments favoris.</French>
|
<French>Met en surbrillance les éléments favoris.</French>
|
||||||
<Portuguese>Cor de destaque para itens favoritados.</Portuguese>
|
<Portuguese>Cor de destaque para itens favoritados.</Portuguese>
|
||||||
<Russian>Выделите цветом любимые предметы.</Russian>
|
<Russian>Выделите цветом любимые предметы.</Russian>
|
||||||
|
<Spanish>Color de marcado para los objetos favoritos</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_buttonFavoritesTooltip">
|
<Key ID="STR_ACE_Arsenal_buttonFavoritesTooltip">
|
||||||
<English>Switch between displaying all items or your favorites.\nDouble click while holding Shift to add or remove an item.</English>
|
<English>Switch between displaying all items or your favorites.\nDouble click while holding Shift to add or remove an item.</English>
|
||||||
@ -1712,6 +1724,7 @@
|
|||||||
<French>Change entre l'affichage de tous les éléments ou de vos favoris.\nDouble-cliquez en maintenant la touche Maj enfoncée pour ajouter ou supprimer un élément.</French>
|
<French>Change entre l'affichage de tous les éléments ou de vos favoris.\nDouble-cliquez en maintenant la touche Maj enfoncée pour ajouter ou supprimer un élément.</French>
|
||||||
<Portuguese>Alterna entre a exibição de todos os itens ou seus favoritos.\nClique duas vezes enquanto mantém pressionada a tecla Shift para adicionar ou remover um item.</Portuguese>
|
<Portuguese>Alterna entre a exibição de todos os itens ou seus favoritos.\nClique duas vezes enquanto mantém pressionada a tecla Shift para adicionar ou remover um item.</Portuguese>
|
||||||
<Russian>Переключайтесь между отображением всех элементов или ваших избранных.\nДважды щелкните, удерживая Shift, чтобы добавить или удалить элемент.</Russian>
|
<Russian>Переключайтесь между отображением всех элементов или ваших избранных.\nДважды щелкните, удерживая Shift, чтобы добавить или удалить элемент.</Russian>
|
||||||
|
<Spanish>Alterna entre mostrar todos los objetos o sólo los favoritos.\nDoble click mientras se pulsa Shift para añadir o quitar un objeto.</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Arsenal_buttonSearchTooltip">
|
<Key ID="STR_ACE_Arsenal_buttonSearchTooltip">
|
||||||
<English>Search\nCTRL + Click to enable live results</English>
|
<English>Search\nCTRL + Click to enable live results</English>
|
||||||
@ -1721,6 +1734,7 @@
|
|||||||
<Korean>검색\nCtrl + 클릭으로 실시간 검색 결과를 활성화</Korean>
|
<Korean>검색\nCtrl + 클릭으로 실시간 검색 결과를 활성화</Korean>
|
||||||
<Russian>Поиск\nCtrl + Click для включения результатов в реальном времени</Russian>
|
<Russian>Поиск\nCtrl + Click для включения результатов в реальном времени</Russian>
|
||||||
<French>Recherche\nCTRL + clic pour modifier les résultats tout en écrivant</French>
|
<French>Recherche\nCTRL + clic pour modifier les résultats tout en écrivant</French>
|
||||||
|
<Spanish>Buscar\nCTRL + Click habilita los objetos en directo</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
</Package>
|
</Package>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
TRACE_1("prep",_this);
|
TRACE_1("prep",_this);
|
||||||
|
|
||||||
|
PREP(adjustFire);
|
||||||
|
PREP(calculateElevation);
|
||||||
|
PREP(calculateMaxAngle);
|
||||||
|
PREP(calculateMuzzleVelocity);
|
||||||
|
PREP(calculateSolution);
|
||||||
PREP(firedEH);
|
PREP(firedEH);
|
||||||
PREP(interactMenuOpened);
|
PREP(interactMenuOpened);
|
||||||
PREP(rangeTableOpen);
|
PREP(rangeTableOpen);
|
||||||
PREP(rangeTableUpdate);
|
PREP(rangeTableUpdate);
|
||||||
|
PREP(simulateShot);
|
||||||
PREP(turretChanged);
|
PREP(turretChanged);
|
||||||
PREP(turretPFEH);
|
PREP(turretPFEH);
|
||||||
|
@ -4,10 +4,13 @@
|
|||||||
TRACE_2("CBA_settingsInitialized",GVAR(advancedCorrections),GVAR(disableArtilleryComputer));
|
TRACE_2("CBA_settingsInitialized",GVAR(advancedCorrections),GVAR(disableArtilleryComputer));
|
||||||
|
|
||||||
if (hasInterface) then {
|
if (hasInterface) then {
|
||||||
// Add hud overlay for actuall azimuth and elevation:
|
// Add hud overlay for actual azimuth and elevation:
|
||||||
GVAR(pfID) = -1;
|
GVAR(pfID) = -1;
|
||||||
["turret", LINKFUNC(turretChanged), true] call CBA_fnc_addPlayerEventHandler;
|
["turret", LINKFUNC(turretChanged), true] call CBA_fnc_addPlayerEventHandler;
|
||||||
|
|
||||||
|
// Handles being teleported from one vehicle to another
|
||||||
|
["vehicle", {[_this select 0, (_this select 1) unitTurret (_this select 0)] call FUNC(turretChanged)}] call CBA_fnc_addPlayerEventHandler;
|
||||||
|
|
||||||
// Add ability to dynamically open rangetables:
|
// Add ability to dynamically open rangetables:
|
||||||
["ace_interactMenuOpened", LINKFUNC(interactMenuOpened)] call CBA_fnc_addEventHandler;
|
["ace_interactMenuOpened", LINKFUNC(interactMenuOpened)] call CBA_fnc_addEventHandler;
|
||||||
};
|
};
|
||||||
@ -30,6 +33,33 @@
|
|||||||
};
|
};
|
||||||
}] call CBA_fnc_addEventHandler;
|
}] call CBA_fnc_addEventHandler;
|
||||||
|
|
||||||
|
addMissionEventHandler ["ExtensionCallback", {
|
||||||
|
params ["_name", "_function", "_data"];
|
||||||
|
if (_name == "ace:artillery" && {_function == "calculate_table"}) then {
|
||||||
|
(parseSimpleArray _data) params ["_line", "_data"];
|
||||||
|
if (_data isEqualType []) then {
|
||||||
|
GVAR(tableData) set [_line, _data];
|
||||||
|
};
|
||||||
|
GVAR(tableSizeReceived) = GVAR(tableSizeReceived) + 1;
|
||||||
|
if (GVAR(tableSizeReceived) == GVAR(tableSizeActual)) then {
|
||||||
|
private _dialog = uiNamespace getVariable [QGVAR(rangeTableDialog), displayNull];
|
||||||
|
private _ctrlRangeTable = _dialog displayCtrl IDC_TABLE;
|
||||||
|
if (isNull _dialog) exitWith {true};
|
||||||
|
for "_i" from 0 to GVAR(tableSizeActual) do {
|
||||||
|
private _row = GVAR(tableData) getOrDefault [_i, []];
|
||||||
|
if (count _row == 12) then {
|
||||||
|
_ctrlRangeTable lnbAddRow _row;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
private _dialog = uiNamespace getVariable [QGVAR(rangeTableDialog), displayNull];
|
||||||
|
private _ctrlRangeTable = _dialog displayCtrl IDC_TABLE;
|
||||||
|
if (isNull _dialog) exitWith {TRACE_1("dialog closed",_this);};
|
||||||
|
_ctrlRangeTable lnbAddRow ["", "", "", "", "", "", "", "", "", "", ""];
|
||||||
|
TRACE_1("table filled",_ctrlRangeTable);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
#ifdef DEBUG_MODE_FULL
|
||||||
#include "dev\showShotInfo.inc.sqf"
|
#include "dev\showShotInfo.inc.sqf"
|
||||||
#include "dev\checkConfigs.inc.sqf"
|
#include "dev\checkConfigs.inc.sqf"
|
||||||
|
@ -14,13 +14,6 @@ class CfgPatches {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ACE_Extensions {
|
|
||||||
class ace_artillerytables {
|
|
||||||
windows = 1;
|
|
||||||
client = 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "CfgEventHandlers.hpp"
|
#include "CfgEventHandlers.hpp"
|
||||||
#include "CfgMagazines.hpp"
|
#include "CfgMagazines.hpp"
|
||||||
#include "CfgVehicles.hpp"
|
#include "CfgVehicles.hpp"
|
||||||
|
41
addons/artillerytables/functions/fnc_adjustFire.sqf
Normal file
41
addons/artillerytables/functions/fnc_adjustFire.sqf
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: LorenLuke
|
||||||
|
* Adjusts a target point north and east, and recalculates a solution in air based on atmospheric conditions
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Gun Position ASL <ARRAY>
|
||||||
|
* 1: Target Position ASL <ARRAY>
|
||||||
|
* 2: Adjustment to the East (negative is West); meters <NUMBER>
|
||||||
|
* 3: Adjustment to the North (negative is South); meters <NUMBER>
|
||||||
|
* 4: Adjustment vertically (negative is Down); meters <NUMBER>
|
||||||
|
* 5: Muzzle velocity; meters/second <NUMBER>
|
||||||
|
* 6: Air Friction; meters^-1 (m/s^2)/(m^2/s^2) <NUMBER>
|
||||||
|
* 7: High angle boolean (true is high angle) <BOOL>
|
||||||
|
* 8: Temperature; degrees Celsius <NUMBER>
|
||||||
|
* 9: Atmospheric Density; kg/(meters^3) <NUMBER>
|
||||||
|
* 10: Direction of wind; degrees clockwise from north <NUMBER>
|
||||||
|
* 11: Speed of wind; meters/second <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Array of returns <ARRAY>
|
||||||
|
* 0: Angle of shot; Milliradians <NUMBER>
|
||||||
|
* 1: Angle adjust left or right; Milliradians <NUMBER>
|
||||||
|
* 2: Time of flight; seconds <NUMBER>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [getposASL vehicle player, targetPos, 20, 50, 0, 200, -0.0001, true, 15, 1.225, 225, 5] call ace_artilleryTables_fnc_adjustFire
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
params ["_gunPos", "_targetPos", "_adjustEast", "_adjustNorth", "_adjustUp", "_muzzleVelocity", "_airFriction", ["_highAngle", true], ["_temperature", 15], ["_airDensity", 1.225], ["_windDir", 0], ["_windSpeed", 0]];
|
||||||
|
|
||||||
|
//DEFAULT_AIR_FRICTION == -0.00006
|
||||||
|
//MK6_82mm_AIR_FRICTION == -0.0001
|
||||||
|
|
||||||
|
private _resultPos = [_adjustEast + _targetPos select 0, _adjustNorth + _targetPos select 1, _adjustUp + _targetPos select 2];
|
||||||
|
|
||||||
|
private _returns = ["_gunPos", "_resultPos", "_muzzleVelocity", "_highAngle", "_airFriction", "_temperature", "_airDensity", "_windDir", "_windSpeed"] call FUNC(calculateSolution);
|
||||||
|
|
||||||
|
_returns
|
71
addons/artillerytables/functions/fnc_calculateElevation.sqf
Normal file
71
addons/artillerytables/functions/fnc_calculateElevation.sqf
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: LorenLuke
|
||||||
|
* Adjusts a target point north and east, and recalculates a solution in air based on atmospheric conditions
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Distance to Target; meters <NUMBER>
|
||||||
|
* 1: Height of target; meters, relative to gun altitude (positive means target higher than gun) <NUMBER>
|
||||||
|
* 2: Muzzle velocity; meters/second <NUMBER>
|
||||||
|
* 3: High angle boolean (true is high angle) <BOOL>
|
||||||
|
* 4: Air Friction; meters^-1 [(m/s^2)/(m^2/s^2)] <NUMBER>
|
||||||
|
* 5: Temperature; degrees Celsius <NUMBER>
|
||||||
|
* 6: Atmospheric Density; kg/(meters^3) <NUMBER>
|
||||||
|
* 7: Cross wind; meters/second (negative is Right to Left) <NUMBER>
|
||||||
|
* 8: Tail wind; meters/second (negative is flying against the wind) <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Array of returns <ARRAY>
|
||||||
|
* 0: Angle of shot; Milliradians <NUMBER>
|
||||||
|
* 1: Angle adjust left or right; Milliradians <NUMBER>
|
||||||
|
* 2: Time of flight; seconds <NUMBER>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [myPos, 0, 200, true, -0.0001, 15, 1.225, 5, -10] call ace_artilleryTables_fnc_calculateElevation
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
params ["_targetDistance", "_targetHeight", "_muzzleVelocity", ["_highArc", true], ["_airFriction", 0], ["_temperature", 15], ["_airDensity", 1.225], ["_crossWind", 0], ["_tailWind", 0]];
|
||||||
|
|
||||||
|
//DEFAULT_AIR_FRICTION == -0.00006
|
||||||
|
//MK6_82mm_AIR_FRICTION == -0.0001
|
||||||
|
|
||||||
|
if (_airFriction != 0) then {
|
||||||
|
_muzzleVelocity = [_muzzleVelocity, _temperature, _atmosphericDensity] call FUNC(calculateMuzzleVelocity);
|
||||||
|
};
|
||||||
|
private _maxResults = [_muzzleVelocity, _airFriction] call FUNC(calculateMaxAngle);
|
||||||
|
|
||||||
|
private _testShot = [_maxResults select 0, _targetHeight, _muzzleVelocity, _airFriction, _crossWind, _tailWind, _temperature, _airDensity] call FUNC(simulateShot);
|
||||||
|
if (_testShot select 1 < _targetDistance) exitWith {
|
||||||
|
//No way we can hit it so don't bother;
|
||||||
|
[-1, -1, -1]
|
||||||
|
};
|
||||||
|
|
||||||
|
private _useDistance = _targetDistance;
|
||||||
|
private _useAngle = 0;
|
||||||
|
private _resultDistance = 0;
|
||||||
|
private _xDeviation = 0;
|
||||||
|
private _tof = 0;
|
||||||
|
|
||||||
|
while {abs(_resultDistance - _targetDistance) > 0.5} do {
|
||||||
|
TRACE_7("callExtension:artillery:simulate_find_solution",_useDistance,_targetHeight,_muzzleVelocity,_airFriction,_higharc,DEFAULT_MIN_ELEV,DEFAULT_MAX_ELEV);
|
||||||
|
(
|
||||||
|
"ace" callExtension ["artillery:simulate_find_solution", [_useDistance, _targetHeight, _muzzleVelocity, _airFriction, _higharc, DEFAULT_MIN_ELEV, DEFAULT_MAX_ELEV]]
|
||||||
|
) params ["_data", "_code"];
|
||||||
|
TRACE_1("",_code);
|
||||||
|
(parseSimpleArray _data) params ["", "_useAngleRad", ""];
|
||||||
|
_useAngle = deg(_useAngleRad) * DEGTOMILS;
|
||||||
|
|
||||||
|
private _shotResults = [_useAngle, _targetHeight, _muzzleVelocity, _airFriction, _crossWind, _tailWind, _temperature, _airDensity] call FUNC(simulateShot);
|
||||||
|
|
||||||
|
_xDeviation = _shotResults select 0;
|
||||||
|
_resultDistance = _shotResults select 1;
|
||||||
|
_tof = _shotResults select 2;
|
||||||
|
_useDistance = (2 * _targetDistance) - _resultDistance;
|
||||||
|
};
|
||||||
|
|
||||||
|
private _angleOffsetDeg = _xDeviation atan2 _resultDistance;
|
||||||
|
private _angleOffset = _angleOffsetDeg * DEGTOMILS;
|
||||||
|
|
||||||
|
[_useAngle, -_angleOffset, _tof]
|
31
addons/artillerytables/functions/fnc_calculateMaxAngle.sqf
Normal file
31
addons/artillerytables/functions/fnc_calculateMaxAngle.sqf
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: LorenLuke
|
||||||
|
* Calculates the best possible angle to shoot farthest based on muzzle velocity and air friction.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Initial Muzzle Velocity; meters/second <NUMBER>
|
||||||
|
* 1: Air Friction; meters^-1 (m/s^2)/(m^2/s^2) <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Values: <ARRAY>
|
||||||
|
* 1: Best Angle; Milliradians <NUMBER>
|
||||||
|
* 2: Furthest Distance; Meters <NUMBER>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [200, -0.00006] call ace_artilleryTables_fnc_calculateMaxAngle
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
params ["_muzzleVelocity", "_airFriction"];
|
||||||
|
|
||||||
|
TRACE_2("callExtension:artillery:find_max_angle",_muzzleVelocity,_airFriction);
|
||||||
|
(
|
||||||
|
"ace" callExtension ["artillery:find_max_angle", [_muzzleVelocity, _airFriction]]
|
||||||
|
) params ["_data", "_code"];
|
||||||
|
TRACE_1("",_code);
|
||||||
|
(parseSimpleArray _data) params ["_bestAngle", "_bestDistance", ""];
|
||||||
|
_returns = [deg _bestAngle * 6400 / 360, _bestDistance];
|
||||||
|
_returns params ["_bestAngle", "_bestDistance"];
|
||||||
|
|
||||||
|
_returns
|
@ -0,0 +1,28 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: LorenLuke
|
||||||
|
* Calculates the muzzleVelocity change with advanced calculations.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Initial Muzzle velocity; meters/second <NUMBER>
|
||||||
|
* 1: Temperature; degrees Celsius <NUMBER>
|
||||||
|
* 2: Atmospheric Density; kg/(meters^3) <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Adjusted Muzzle Velocity; Meters <NUMBER>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [200, 15, 1.225] call ace_artilleryTables_fnc_calculateMuzzleVelocity
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
params ["_muzzleVelocity", "_temperature", "_airDensity"];
|
||||||
|
|
||||||
|
// Calculate air density
|
||||||
|
private _relativeDensity = _airDensity / 1.225;
|
||||||
|
private _newMuzzleVelocityCoefficient = (((_temperature + 273.13) / 288.13 - 1) / 40 + 1);
|
||||||
|
|
||||||
|
private _newMuzzleVelocity = _muzzleVelocity * _newMuzzleVelocityCoefficient;
|
||||||
|
|
||||||
|
_newMuzzleVelocity
|
44
addons/artillerytables/functions/fnc_calculateSolution.sqf
Normal file
44
addons/artillerytables/functions/fnc_calculateSolution.sqf
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: LorenLuke
|
||||||
|
* Provides fire angle and deflection solutions on a target of set distance and height, including accounting for drag and atmospheric wind conditions.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Gun Position ASL; <ARRAY>
|
||||||
|
* 1: Target Position ASL; <ARRAY>
|
||||||
|
* 2: Muzzle Velocity; meters/second <NUMBER>
|
||||||
|
* 3: High angle boolean (true is high angle) <BOOL>
|
||||||
|
* 4: Air Friction; meters^-1 [(m/s^2)/(m^2/s^2)] <NUMBER>
|
||||||
|
* 5: Temperature; degrees Celsius <NUMBER>
|
||||||
|
* 6: Atmospheric Density; kg/(meters^3) <NUMBER>
|
||||||
|
* 7: Direction of wind; degrees clockwise from north <NUMBER>
|
||||||
|
* 8: Speed of wind; meters/second <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* array of returns <ARRAY>
|
||||||
|
* 0: Angle of shot; Milliradians <NUMBER>
|
||||||
|
* 1: Angle adjust left or right; Milliradians <NUMBER>
|
||||||
|
* 2: Time of flight; seconds <NUMBER>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [myPos, targetPos, 200, true, -0.0001, 15, 1.225, 225, 5] call ace_artilleryTables_fnc_calculateSolution
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
params ["_ownPos", "_targetPos", "_muzzleVelocity", ["_highAngle", true], ["_airFriction", 0], ["_temperature", 15], ["_airDensity", 1.225], ["_windDir", 0], ["_windSpeed", 0]];
|
||||||
|
|
||||||
|
//DEFAULT_AIR_FRICTION == -0.00006
|
||||||
|
//MK6_82mm_AIR_FRICTION == -0.0001
|
||||||
|
|
||||||
|
private _relPos = _targetPos vectorDiff _ownPos;
|
||||||
|
|
||||||
|
private _targetDir = (_relpos select 0) atan2 (_relPos select 1);
|
||||||
|
private _targetDist = sqrt( (_relPos select 0)^2 + (_relpos select 1)^2 );
|
||||||
|
private _heightDif = _relPos select 2;
|
||||||
|
private _crossWind = sin(_targetDir - _windDir) * _windSpeed;
|
||||||
|
private _tailWind = -cos(_targetDir - _windDir) * _windSpeed;
|
||||||
|
|
||||||
|
private _solutionReturns = [_targetDist, _heightDif, _muzzleVelocity, _highAngle, _airFriction, _crossWind, _tailWind, _temperature, _airDensity] call FUNC(calculateElevation);
|
||||||
|
|
||||||
|
_solutionReturns
|
@ -25,7 +25,7 @@
|
|||||||
params ["_vehicle", "", "", "", "", "_magazine", "_projectile", "_gunner"];
|
params ["_vehicle", "", "", "", "", "_magazine", "_projectile", "_gunner"];
|
||||||
TRACE_4("firedEH",_vehicle,_magazine,_projectile,_gunner);
|
TRACE_4("firedEH",_vehicle,_magazine,_projectile,_gunner);
|
||||||
|
|
||||||
if (!([_gunner] call EFUNC(common,isPlayer))) exitWith {}; // AI don't know how to use (this does give them more range than a player)
|
if !([_gunner] call EFUNC(common,isPlayer)) exitWith {}; // AI don't know how to use (this does give them more range than a player)
|
||||||
if ((gunner _vehicle) != _gunner) exitWith {}; // check if primaryGunner
|
if ((gunner _vehicle) != _gunner) exitWith {}; // check if primaryGunner
|
||||||
|
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ if (isNumber (configFile >> "CfgMagazines" >> _magazine >> QGVAR(airFriction)))
|
|||||||
_airFriction = getNumber (configFile >> "CfgMagazines" >> _magazine >> QGVAR(airFriction));
|
_airFriction = getNumber (configFile >> "CfgMagazines" >> _magazine >> QGVAR(airFriction));
|
||||||
};
|
};
|
||||||
TRACE_1("",_airFriction);
|
TRACE_1("",_airFriction);
|
||||||
if (_airFriction >= 0) exitWith {}; // 0 disables everything, >0 makes no sense
|
if (_airFriction == 0) exitWith {}; // 0 disables everything
|
||||||
|
|
||||||
BEGIN_COUNTER(adjustmentsCalc);
|
BEGIN_COUNTER(adjustmentsCalc);
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ if (_newMuzzleVelocityCoefficent != 1) then {
|
|||||||
_projectile setVelocity _bulletVelocity;
|
_projectile setVelocity _bulletVelocity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (_airFriction > 0) exitWith {}; // positive value indicates it has vanilla airFriction, so we can just exit
|
||||||
|
|
||||||
[{
|
[{
|
||||||
params ["_projectile", "_kFactor", "_time"];
|
params ["_projectile", "_kFactor", "_time"];
|
||||||
|
@ -19,7 +19,7 @@ params ["_menuType"];
|
|||||||
TRACE_1("interactMenuOpened",_menuType);
|
TRACE_1("interactMenuOpened",_menuType);
|
||||||
|
|
||||||
if (_menuType != 1) exitWith {};
|
if (_menuType != 1) exitWith {};
|
||||||
if (!("ACE_artilleryTable" in (ace_player call EFUNC(common,uniqueItems)))) exitWith {};
|
if !("ACE_artilleryTable" in (ace_player call EFUNC(common,uniqueItems))) exitWith {};
|
||||||
|
|
||||||
private _vehicleAdded = ace_player getVariable [QGVAR(vehiclesAdded), []];
|
private _vehicleAdded = ace_player getVariable [QGVAR(vehiclesAdded), []];
|
||||||
private _rangeTablesShown = ace_player getVariable [QGVAR(rangeTablesShown), []];
|
private _rangeTablesShown = ace_player getVariable [QGVAR(rangeTablesShown), []];
|
||||||
|
@ -34,15 +34,22 @@ TRACE_2("created dialog",_dialog,_ctrlChargeList);
|
|||||||
|
|
||||||
// Get Mags:
|
// Get Mags:
|
||||||
private _mags = [_weaponName] call CBA_fnc_compatibleMagazines;
|
private _mags = [_weaponName] call CBA_fnc_compatibleMagazines;
|
||||||
if (_mags isEqualTo []) exitWith {WARNING_1("No Mags",_weaponName);};
|
if (_mags isEqualTo []) exitWith {WARNING_1("No Mags %1",_weaponName);};
|
||||||
private _magCfg = configFile >> "CfgMagazines";
|
private _magCfg = configFile >> "CfgMagazines";
|
||||||
private _magParamsArray = [];
|
private _magParamsArray = [];
|
||||||
_mags = _mags apply {
|
_mags = _mags apply {
|
||||||
private _initSpeed = getNumber (_magCfg >> _x >> "initSpeed");
|
private _initSpeed = getNumber (_magCfg >> _x >> "initSpeed");
|
||||||
_magParamsArray pushBackUnique _initSpeed;
|
_magParamsArray pushBackUnique _initSpeed;
|
||||||
private _airFriction = 0;
|
private _airFriction = 0;
|
||||||
if (_advCorrection) then {
|
private _magAirFriction = getNumber (_magCfg >> _x >> QGVAR(airFriction));
|
||||||
_airFriction = if (isNumber (_magCfg >> _x >> QGVAR(airFriction))) then { getNumber (_magCfg >> _x >> QGVAR(airFriction)) } else { DEFAULT_AIR_FRICTION };
|
if (_magAirFriction <= 0) then {
|
||||||
|
if (_advCorrection) then {
|
||||||
|
_airFriction = [DEFAULT_AIR_FRICTION, _magAirFriction] select (isNumber (_magCfg >> _x >> QGVAR(airFriction)));
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// positive value, use ammo's airFriction (regardless of setting)
|
||||||
|
private _ammo = getText (_magCfg >> _x >> "ammo");
|
||||||
|
_airFriction = getNumber (configFile >> "CfgAmmo" >> _ammo >> "airFriction");
|
||||||
};
|
};
|
||||||
_magParamsArray pushBackUnique _airFriction;
|
_magParamsArray pushBackUnique _airFriction;
|
||||||
[getText (_magCfg >> _x >> "displayNameShort"), getText (_magCfg >> _x >> "displayName"), _initSpeed, _airFriction]
|
[getText (_magCfg >> _x >> "displayNameShort"), getText (_magCfg >> _x >> "displayName"), _initSpeed, _airFriction]
|
||||||
|
@ -34,31 +34,12 @@ _ctrlElevationLow ctrlSetTextColor ([[1,1,1,1],[0.25,0.25,0.25,1]] select GVAR(l
|
|||||||
|
|
||||||
lnbClear _ctrlRangeTable;
|
lnbClear _ctrlRangeTable;
|
||||||
// Call extension with current data and start workers
|
// Call extension with current data and start workers
|
||||||
TRACE_5("callExtension:start",_muzzleVelocity,_airFriction,_elevMin,_elevMax,GVAR(lastElevationMode));
|
TRACE_5("callExtension:artillery:calculate_table",_muzzleVelocity,_airFriction,_elevMin,_elevMax,GVAR(lastElevationMode));
|
||||||
private _ret = "ace_artillerytables" callExtension ["start", [_muzzleVelocity,_airFriction,_elevMin,_elevMax,GVAR(lastElevationMode)]];
|
(
|
||||||
TRACE_1("",_ret);
|
"ace" callExtension ["artillery:calculate_table", [_muzzleVelocity, _airFriction, _elevMin, _elevMax, GVAR(lastElevationMode)]]
|
||||||
|
) params ["_data", "_code"];
|
||||||
|
TRACE_1("",_code);
|
||||||
|
|
||||||
// Non-blocking read data out of extension as it becomes availiable
|
GVAR(tableData) = createHashMap;
|
||||||
[{
|
GVAR(tableSizeActual) = (parseSimpleArray _data) select 1;
|
||||||
private _dialog = uiNamespace getVariable [QGVAR(rangeTableDialog), displayNull];
|
GVAR(tableSizeReceived) = 0;
|
||||||
private _ctrlRangeTable = _dialog displayCtrl IDC_TABLE;
|
|
||||||
if (isNull _dialog) exitWith {true};
|
|
||||||
|
|
||||||
private _status = 1; // 1 = data on line, 2 - data not ready, 3 - done
|
|
||||||
while {_status == 1} do {
|
|
||||||
private _ret = ("ace_artillerytables" callExtension ["getline", []]);
|
|
||||||
// TRACE_1("callExtension:getline",_ret);
|
|
||||||
_status = _ret select 1;
|
|
||||||
if (_status == 1) then { _ctrlRangeTable lnbAddRow parseSimpleArray (_ret select 0) };
|
|
||||||
};
|
|
||||||
|
|
||||||
(_status == 3) // exit loop when all data read
|
|
||||||
}, {
|
|
||||||
// put dummy line at end because scrolling is problematic and can't see last line
|
|
||||||
private _dialog = uiNamespace getVariable [QGVAR(rangeTableDialog), displayNull];
|
|
||||||
private _ctrlRangeTable = _dialog displayCtrl IDC_TABLE;
|
|
||||||
if (isNull _dialog) exitWith {TRACE_1("dialog closed",_this);};
|
|
||||||
|
|
||||||
_ctrlRangeTable lnbAddRow ["", "", "", "", "", "", "", "", "", "", ""];
|
|
||||||
TRACE_1("table filled",_ctrlRangeTable);
|
|
||||||
}, []] call CBA_fnc_waitUntilAndExecute;
|
|
||||||
|
47
addons/artillerytables/functions/fnc_simulateShot.sqf
Normal file
47
addons/artillerytables/functions/fnc_simulateShot.sqf
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: LorenLuke
|
||||||
|
* Simulates an indirect shot on a target of known height with given drag, wind, and atmospheric conditions
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Gun Elevation Angle; milliradians <NUMBER>
|
||||||
|
* 1: Relative Target Height; meters, relative to gun altitude (positive means target higher than gun) <NUMBER>
|
||||||
|
* 2: Muzzle Velocity; meters/second <NUMBER>
|
||||||
|
* 3: Air Friction; meters^-1 [(m/s^2)/(m^2/s^2)] <NUMBER>
|
||||||
|
* 4: Cross wind; meters/second (negative is Right to Left) <NUMBER>
|
||||||
|
* 5: Tail wind; meters/second (negative is flying against the wind) <NUMBER>
|
||||||
|
* 6: Temperature; degrees Celsius <NUMBER>
|
||||||
|
* 7: Atmospheric Density; kg/(meters^3) <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* array of returns <ARRAY>
|
||||||
|
* 0: Deflection Adjustment To Hit; Milliradians (negative is Left) <NUMBER>
|
||||||
|
* 1: Distance of Shot; meters <NUMBER>
|
||||||
|
* 2: Time of Flight; seconds <NUMBER>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [900, 10, 200, -0.0001, 4, 0, 15, 1.225] call ace_artilleryTables_fnc_simulateShot
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
params ["_angle", "_targetHeight", "_muzzleVelocity", ["_airFriction", 0], ["_crossWind", 0], ["_tailWind", 0], ["_temperature", 15], ["_atmosphericDensity", 1.225]];
|
||||||
|
|
||||||
|
//DEFAULT_AIR_FRICTION == -0.00006
|
||||||
|
//MK6_82mm_AIR_FRICTION == -0.0001
|
||||||
|
|
||||||
|
if (_airFriction != 0) then {
|
||||||
|
_muzzleVelocity = [_muzzleVelocity, _temperature, _atmosphericDensity] call FUNC(calculateMuzzleVelocity);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _atmosphericDensityRatio = _atmosphericDensity / 1.225;
|
||||||
|
private _radAngle = rad(_angle / DEGTOMILS);
|
||||||
|
|
||||||
|
TRACE_8("callExtension:artillery:simulate_shot",_radAngle,_targetHeight,_muzzleVelocity,_airFriction,_crossWind,_tailWind,_temperature,_atmosphericDensityRatio);
|
||||||
|
(
|
||||||
|
"ace" callExtension ["artillery:simulate_shot", [_radAngle, _targetHeight, _muzzleVelocity, _airFriction, _crossWind, _tailWind, _temperature, _atmosphericDensityRatio]]
|
||||||
|
) params ["_data", "_code"];
|
||||||
|
TRACE_1("",_code);
|
||||||
|
|
||||||
|
//[xDeviation, yDistance, timeOfFlight]
|
||||||
|
parseSimpleArray _data
|
@ -30,7 +30,10 @@ if (isNull (uiNamespace getVariable [QGVAR(display), displayNull])) then {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private _ctrlGroup = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl 1000;
|
private _ctrlGroup = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl 1000;
|
||||||
if (cameraView != "GUNNER") exitWith { // need to be in gunner mode, so we can check where the optics are aiming at
|
|
||||||
|
// Need to be in gunner mode, so we can check where the optics are aiming at
|
||||||
|
// However, if there are no optics, ignore the above
|
||||||
|
if (!_invalidGunnerMem && {cameraView != "GUNNER"}) exitWith {
|
||||||
_ctrlGroup ctrlShow false;
|
_ctrlGroup ctrlShow false;
|
||||||
};
|
};
|
||||||
_ctrlGroup ctrlShow true;
|
_ctrlGroup ctrlShow true;
|
||||||
|
@ -15,7 +15,5 @@ private _categoryName = [format ["ACE %1", localize "str_a3_cfgmarkers_nato_art"
|
|||||||
[LSTRING(disableArtilleryComputer_displayName), LSTRING(disableArtilleryComputer_description)],
|
[LSTRING(disableArtilleryComputer_displayName), LSTRING(disableArtilleryComputer_description)],
|
||||||
_categoryName,
|
_categoryName,
|
||||||
false, // default value
|
false, // default value
|
||||||
true, // isGlobal
|
true // isGlobal
|
||||||
{[QGVAR(disableArtilleryComputer), _this] call EFUNC(common,cbaSettings_settingChanged)},
|
|
||||||
false // Needs mission restart
|
|
||||||
] call CBA_fnc_addSetting;
|
] call CBA_fnc_addSetting;
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
// This is a good fit for most large artillery, but a little low for lighter mortars
|
// This is a good fit for most large artillery, but a little low for lighter mortars
|
||||||
#define DEFAULT_AIR_FRICTION -0.00006
|
#define DEFAULT_AIR_FRICTION -0.00006
|
||||||
|
|
||||||
|
#define DEFAULT_MIN_ELEV 0
|
||||||
|
// 90 degrees in radians
|
||||||
|
#define DEFAULT_MAX_ELEV 1.5708
|
||||||
|
|
||||||
#define DEGTOMILS 17.7777778
|
#define DEGTOMILS 17.7777778
|
||||||
|
|
||||||
#define IDC_MODECONTROLGROUP 1000
|
#define IDC_MODECONTROLGROUP 1000
|
||||||
|
@ -6,7 +6,7 @@ class CfgPatches {
|
|||||||
units[] = {"ACE_Item_ATragMX"};
|
units[] = {"ACE_Item_ATragMX"};
|
||||||
weapons[] = {"ACE_ATragMX"};
|
weapons[] = {"ACE_ATragMX"};
|
||||||
requiredVersion = REQUIRED_VERSION;
|
requiredVersion = REQUIRED_VERSION;
|
||||||
requiredAddons[] = {"ACE_Advanced_Ballistics", "ACE_common", "ACE_weather"};
|
requiredAddons[] = {"ace_advanced_ballistics", "ace_common", "ace_weather"};
|
||||||
author = ECSTRING(common,ACETeam);
|
author = ECSTRING(common,ACETeam);
|
||||||
authors[] = {"Ruthberg"};
|
authors[] = {"Ruthberg"};
|
||||||
url = ECSTRING(main,URL);
|
url = ECSTRING(main,URL);
|
||||||
|
@ -30,9 +30,16 @@ while {_velocity > _thresholdVelocity} do {
|
|||||||
private _bc = GVAR(targetSolutionInput) select 14;
|
private _bc = GVAR(targetSolutionInput) select 14;
|
||||||
private _dragModel = GVAR(targetSolutionInput) select 15;
|
private _dragModel = GVAR(targetSolutionInput) select 15;
|
||||||
private _temperature = GVAR(targetSolutionInput) select 5;
|
private _temperature = GVAR(targetSolutionInput) select 5;
|
||||||
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3:%4", _dragModel, _bc, _velocity, _temperature]));
|
|
||||||
_distance = _distance + _velocity * __DELTA_T;
|
_distance = _distance + _velocity * __DELTA_T;
|
||||||
_velocity = _velocity - (_drag * __DELTA_T);
|
private _data = (
|
||||||
|
"ace" callExtension ["ballistics:retard", [
|
||||||
|
_dragModel,
|
||||||
|
_bc,
|
||||||
|
_velocity,
|
||||||
|
_temperature
|
||||||
|
]]
|
||||||
|
) select 0;
|
||||||
|
_velocity = _velocity - ((parseNumber _data) * __DELTA_T);
|
||||||
};
|
};
|
||||||
|
|
||||||
_distance
|
_distance
|
||||||
|
@ -90,7 +90,14 @@ private _wind1 = [cos(270 - _windDirection * 30) * _windSpeed1, sin(270 - _windD
|
|||||||
private _wind2 = [cos(270 - _windDirection * 30) * _windSpeed2, sin(270 - _windDirection * 30) * _windSpeed2, 0];
|
private _wind2 = [cos(270 - _windDirection * 30) * _windSpeed2, sin(270 - _windDirection * 30) * _windSpeed2, 0];
|
||||||
private _windDrift = 0;
|
private _windDrift = 0;
|
||||||
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
|
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
|
||||||
_bc = parseNumber(("ace_advanced_ballistics" callExtension format["atmosphericCorrection:%1:%2:%3:%4:%5", _bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel]));
|
_bc = parseNumber (("ace" callExtension ["ballistics:atmospheric_correction", [
|
||||||
|
_bc,
|
||||||
|
_temperature,
|
||||||
|
_barometricPressure,
|
||||||
|
_relativeHumidity,
|
||||||
|
_atmosphereModel
|
||||||
|
]]
|
||||||
|
) select 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
private _eoetvoesMultiplier = 0;
|
private _eoetvoesMultiplier = 0;
|
||||||
@ -113,8 +120,15 @@ while {_TOF < 15 && (_bulletPos select 1) < _targetRange} do {
|
|||||||
_trueSpeed = vectorMagnitude _trueVelocity;
|
_trueSpeed = vectorMagnitude _trueVelocity;
|
||||||
|
|
||||||
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
|
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
|
||||||
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3:%4", _dragModel, _bc, _trueSpeed, _temperature]));
|
private _data = (
|
||||||
_bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag);
|
"ace" callExtension ["ballistics:retard", [
|
||||||
|
_dragModel,
|
||||||
|
_bc,
|
||||||
|
_trueSpeed,
|
||||||
|
_temperature
|
||||||
|
]]
|
||||||
|
) select 0;
|
||||||
|
_bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * (parseNumber _data));
|
||||||
} else {
|
} else {
|
||||||
_bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction);
|
_bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction);
|
||||||
};
|
};
|
||||||
|
@ -23,7 +23,7 @@ if ((profileNamespace getVariable ["ACE_ATragMX_profileNamespaceVersion", 0]) ==
|
|||||||
_resetGunList = false;
|
_resetGunList = false;
|
||||||
{
|
{
|
||||||
// Verify each gun has correct param type
|
// Verify each gun has correct param type
|
||||||
if (!(_x isEqualTypeArray ["", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", [], [], false])) exitWith {
|
if !(_x isEqualTypeArray ["", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", [], [], false]) exitWith {
|
||||||
_resetGunList = true;
|
_resetGunList = true;
|
||||||
};
|
};
|
||||||
} forEach GVAR(gunList);
|
} forEach GVAR(gunList);
|
||||||
|
@ -74,7 +74,7 @@ private _validate_preset = {
|
|||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
_valid = false;
|
_valid = false;
|
||||||
};
|
};
|
||||||
if (!((_this select 17) in ["ASM", "ICAO"])) then {
|
if !((_this select 17) in ["ASM", "ICAO"]) then {
|
||||||
private _errorMsg = format ["Invalid atmosphere model: %1", _this select 17];
|
private _errorMsg = format ["Invalid atmosphere model: %1", _this select 17];
|
||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
_valid = false;
|
_valid = false;
|
||||||
|
@ -26,7 +26,7 @@ if !(ctrlVisible 9000) then {
|
|||||||
params ["_args"];
|
params ["_args"];
|
||||||
_args params ["_startTime"];
|
_args params ["_startTime"];
|
||||||
|
|
||||||
if (!(GVAR(speedAssistTimer))) exitWith {
|
if !(GVAR(speedAssistTimer)) exitWith {
|
||||||
GVAR(speedAssistTimer) = true;
|
GVAR(speedAssistTimer) = true;
|
||||||
|
|
||||||
ctrlSetText [8006, Str(Round((CBA_missionTime - _startTime) * 10) / 10)];
|
ctrlSetText [8006, Str(Round((CBA_missionTime - _startTime) * 10) / 10)];
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) exitWith {};
|
if !(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) exitWith {};
|
||||||
|
|
||||||
if (ctrlVisible 17000) then {
|
if (ctrlVisible 17000) then {
|
||||||
false call FUNC(show_c1_ballistic_coefficient_data);
|
false call FUNC(show_c1_ballistic_coefficient_data);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) exitWith {};
|
if !(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) exitWith {};
|
||||||
|
|
||||||
if (ctrlVisible 16000) then {
|
if (ctrlVisible 16000) then {
|
||||||
false call FUNC(show_muzzle_velocity_data);
|
false call FUNC(show_muzzle_velocity_data);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) exitWith {};
|
if !(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) exitWith {};
|
||||||
|
|
||||||
if (ctrlVisible 18000) then {
|
if (ctrlVisible 18000) then {
|
||||||
false call FUNC(show_truing_drop);
|
false call FUNC(show_truing_drop);
|
||||||
|
@ -35,12 +35,26 @@ if (!GVAR(atmosphereModeTBH)) then {
|
|||||||
_relativeHumidity = 0.5;
|
_relativeHumidity = 0.5;
|
||||||
};
|
};
|
||||||
|
|
||||||
private _scopeBaseAngle = if (!(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) then {
|
private _scopeBaseAngle = if !(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
|
||||||
private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZero:%1:%2:%3:%4", _zeroRange, _muzzleVelocity, _airFriction, _boreHeight];
|
parseNumber (("ace" callExtension ["ballistics:zero_vanilla", [
|
||||||
(parseNumber _zeroAngle)
|
_zeroRange,
|
||||||
|
_muzzleVelocity,
|
||||||
|
_airFriction,
|
||||||
|
_boreHeight
|
||||||
|
]]) select 0)
|
||||||
} else {
|
} else {
|
||||||
private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZeroAB:%1:%2:%3:%4:%5:%6:%7:%8:%9", _zeroRange, _muzzleVelocity, _boreHeight, _temperature, _barometricPressure, _relativeHumidity, _bc, _dragModel, _atmosphereModel];
|
parseNumber (("ace" callExtension ["ballistics:zero_advanced", [
|
||||||
(parseNumber _zeroAngle)
|
_zeroRange,
|
||||||
|
_muzzleVelocity,
|
||||||
|
_airFriction,
|
||||||
|
_boreHeight,
|
||||||
|
_temperature,
|
||||||
|
_barometricPressure,
|
||||||
|
_relativeHumidity,
|
||||||
|
_bc,
|
||||||
|
_dragModel,
|
||||||
|
_atmosphereModel
|
||||||
|
]]) select 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
GVAR(workingMemory) set [2, _zeroRange];
|
GVAR(workingMemory) set [2, _zeroRange];
|
||||||
|
@ -50,8 +50,8 @@ if (_unit == _attachToVehicle) then { //Self Attachment
|
|||||||
} else {
|
} else {
|
||||||
GVAR(placeAction) = PLACE_WAITING;
|
GVAR(placeAction) = PLACE_WAITING;
|
||||||
|
|
||||||
[_unit, "forceWalk", "ACE_Attach", true] call EFUNC(common,statusEffect_set);
|
[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
||||||
[_unit, "blockThrow", "ACE_Attach", true] call EFUNC(common,statusEffect_set);
|
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
|
||||||
|
|
||||||
[{[localize LSTRING(PlaceAction), ""] call EFUNC(interaction,showMouseHint)}, []] call CBA_fnc_execNextFrame;
|
[{[localize LSTRING(PlaceAction), ""] call EFUNC(interaction,showMouseHint)}, []] call CBA_fnc_execNextFrame;
|
||||||
_unit setVariable [QGVAR(placeActionEH), [_unit, "DefaultAction", {true}, {GVAR(placeAction) = PLACE_APPROVE;}] call EFUNC(common,AddActionEventHandler)];
|
_unit setVariable [QGVAR(placeActionEH), [_unit, "DefaultAction", {true}, {GVAR(placeAction) = PLACE_APPROVE;}] call EFUNC(common,AddActionEventHandler)];
|
||||||
@ -88,8 +88,8 @@ if (_unit == _attachToVehicle) then { //Self Attachment
|
|||||||
{!([_attachToVehicle, _unit, _itemClassname] call FUNC(canAttach))}) then {
|
{!([_attachToVehicle, _unit, _itemClassname] call FUNC(canAttach))}) then {
|
||||||
|
|
||||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||||
[_unit, "forceWalk", "ACE_Attach", false] call EFUNC(common,statusEffect_set);
|
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
||||||
[_unit, "blockThrow", "ACE_Attach", false] call EFUNC(common,statusEffect_set);
|
[_unit, "blockThrow", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
|
||||||
[] call EFUNC(interaction,hideMouseHint);
|
[] call EFUNC(interaction,hideMouseHint);
|
||||||
[_unit, "DefaultAction", (_unit getVariable [QGVAR(placeActionEH), -1])] call EFUNC(common,removeActionEventHandler);
|
[_unit, "DefaultAction", (_unit getVariable [QGVAR(placeActionEH), -1])] call EFUNC(common,removeActionEventHandler);
|
||||||
_unit removeAction _actionID;
|
_unit removeAction _actionID;
|
||||||
|
@ -28,7 +28,7 @@ if (_attachedList isEqualTo []) exitWith {};
|
|||||||
TRACE_2("detaching",_xObject,_deadUnit);
|
TRACE_2("detaching",_xObject,_deadUnit);
|
||||||
detach _xObject;
|
detach _xObject;
|
||||||
//If it's a vehicle, also delete the attached
|
//If it's a vehicle, also delete the attached
|
||||||
if (!(_deadUnit isKindOf "CAManBase")) then {
|
if !(_deadUnit isKindOf "CAManBase") then {
|
||||||
_xObject setPos ((getPos _deadUnit) vectorAdd [0, 0, -1000]);
|
_xObject setPos ((getPos _deadUnit) vectorAdd [0, 0, -1000]);
|
||||||
[{deleteVehicle (_this select 0)}, [_xObject], 2] call CBA_fnc_waitAndExecute;
|
[{deleteVehicle (_this select 0)}, [_xObject], 2] call CBA_fnc_waitAndExecute;
|
||||||
};
|
};
|
||||||
|
@ -1505,7 +1505,7 @@
|
|||||||
<Portuguese>Carregador de 10 cartuchos 9.3 mm traçantes IR-DIM</Portuguese>
|
<Portuguese>Carregador de 10 cartuchos 9.3 mm traçantes IR-DIM</Portuguese>
|
||||||
<Hungarian>9,3 mm 10-lövedékes infravörös nyomkövető tár</Hungarian>
|
<Hungarian>9,3 mm 10-lövedékes infravörös nyomkövető tár</Hungarian>
|
||||||
<Japanese>9.3mm 10Rnd IR-DIM トレーサー マガジン</Japanese>
|
<Japanese>9.3mm 10Rnd IR-DIM トレーサー マガジン</Japanese>
|
||||||
<Korean>10발들이 9.3mm IR-DIM 예광탄 탄창</Korean>
|
<Korean>10발 들이 9.3mm IR-DIM 예광탄 탄창</Korean>
|
||||||
<Chinese>9.3毫米 10發 低視度紅外線曳光彈 彈匣</Chinese>
|
<Chinese>9.3毫米 10發 低視度紅外線曳光彈 彈匣</Chinese>
|
||||||
<Chinesesimp>9.3 mm 10发 弹匣(红外曳光)</Chinesesimp>
|
<Chinesesimp>9.3 mm 10发 弹匣(红外曳光)</Chinesesimp>
|
||||||
<Turkish>9.3 mm 10Rnd Tracer IR-DIM Mag</Turkish>
|
<Turkish>9.3 mm 10Rnd Tracer IR-DIM Mag</Turkish>
|
||||||
@ -1608,7 +1608,7 @@
|
|||||||
<Portuguese>Cinto de munição traçante 9.3 mm IR-DIM com 150 cartuchos</Portuguese>
|
<Portuguese>Cinto de munição traçante 9.3 mm IR-DIM com 150 cartuchos</Portuguese>
|
||||||
<Hungarian>9,3 mm 150-lövedékes infravörös nyomkövető heveder</Hungarian>
|
<Hungarian>9,3 mm 150-lövedékes infravörös nyomkövető heveder</Hungarian>
|
||||||
<Japanese>9.3mm 150Rnd IR-DIM トレーサー ベルト</Japanese>
|
<Japanese>9.3mm 150Rnd IR-DIM トレーサー ベルト</Japanese>
|
||||||
<Korean>150발들이 9.3mm IR-DIM 예광탄 벨트</Korean>
|
<Korean>150발 들이 9.3mm IR-DIM 예광탄 벨트</Korean>
|
||||||
<Chinese>9.3毫米 150發 低視度紅外線曳光彈 彈鏈</Chinese>
|
<Chinese>9.3毫米 150發 低視度紅外線曳光彈 彈鏈</Chinese>
|
||||||
<Chinesesimp>9.3 mm 150发 弹链(红外曳光)</Chinesesimp>
|
<Chinesesimp>9.3 mm 150发 弹链(红外曳光)</Chinesesimp>
|
||||||
<Turkish>9.3 mm 150Rnd Tracer IR-DIM Belt</Turkish>
|
<Turkish>9.3 mm 150Rnd Tracer IR-DIM Belt</Turkish>
|
||||||
@ -1659,7 +1659,7 @@
|
|||||||
<Portuguese>Cinto de munição 9.3 mm AP com 150 cartuchos</Portuguese>
|
<Portuguese>Cinto de munição 9.3 mm AP com 150 cartuchos</Portuguese>
|
||||||
<Hungarian>9,3 mm 150-lövedékes páncéltörő heveder</Hungarian>
|
<Hungarian>9,3 mm 150-lövedékes páncéltörő heveder</Hungarian>
|
||||||
<Japanese>9.3mm 150Rnd 徹甲弾 ベルト</Japanese>
|
<Japanese>9.3mm 150Rnd 徹甲弾 ベルト</Japanese>
|
||||||
<Korean>150발들이 9.3mm 철갑탄 벨트</Korean>
|
<Korean>150발 들이 9.3mm 철갑탄 벨트</Korean>
|
||||||
<Chinese>9.3毫米 150發 穿甲彈 彈鏈</Chinese>
|
<Chinese>9.3毫米 150發 穿甲彈 彈鏈</Chinese>
|
||||||
<Chinesesimp>9.3 mm 150发 弹链(穿甲)</Chinesesimp>
|
<Chinesesimp>9.3 mm 150发 弹链(穿甲)</Chinesesimp>
|
||||||
<Turkish>9.3 mm 150Rnd AP Belt</Turkish>
|
<Turkish>9.3 mm 150Rnd AP Belt</Turkish>
|
||||||
@ -1710,7 +1710,7 @@
|
|||||||
<Portuguese>Carregador de 16 cartuchos 9x19 mm</Portuguese>
|
<Portuguese>Carregador de 16 cartuchos 9x19 mm</Portuguese>
|
||||||
<Hungarian>9x19 mm 16-lövedékes tár</Hungarian>
|
<Hungarian>9x19 mm 16-lövedékes tár</Hungarian>
|
||||||
<Japanese>9x19 mm 16Rnd マガジン</Japanese>
|
<Japanese>9x19 mm 16Rnd マガジン</Japanese>
|
||||||
<Korean>17발들이 9x19mm 탄창</Korean>
|
<Korean>16발 들이 9x19mm 탄창</Korean>
|
||||||
<Chinese>9x19毫米 16發 彈匣</Chinese>
|
<Chinese>9x19毫米 16發 彈匣</Chinese>
|
||||||
<Chinesesimp>9x19 mm 16发 弹匣</Chinesesimp>
|
<Chinesesimp>9x19 mm 16发 弹匣</Chinesesimp>
|
||||||
<Turkish>9x19 mm 16Rnd Mag</Turkish>
|
<Turkish>9x19 mm 16Rnd Mag</Turkish>
|
||||||
@ -2016,7 +2016,7 @@
|
|||||||
<Portuguese>Carregador 5.56 mm com 30 cartuchos (Mk318)</Portuguese>
|
<Portuguese>Carregador 5.56 mm com 30 cartuchos (Mk318)</Portuguese>
|
||||||
<Hungarian>5,56 mm 30-lövedékes tár (Mk318)</Hungarian>
|
<Hungarian>5,56 mm 30-lövedékes tár (Mk318)</Hungarian>
|
||||||
<Japanese>5.56mm 30Rnd マガジン (Mk318)</Japanese>
|
<Japanese>5.56mm 30Rnd マガジン (Mk318)</Japanese>
|
||||||
<Korean>30발들이 5.56mm 탄창 (Mk.318)</Korean>
|
<Korean>30발 들이 5.56mm 탄창 (Mk.318)</Korean>
|
||||||
<Chinese>5.56毫米 30發 彈匣 (Mk318 特戰專用彈)</Chinese>
|
<Chinese>5.56毫米 30發 彈匣 (Mk318 特戰專用彈)</Chinese>
|
||||||
<Chinesesimp>5.56 mm 30发 弹匣(Mk318)</Chinesesimp>
|
<Chinesesimp>5.56 mm 30发 弹匣(Mk318)</Chinesesimp>
|
||||||
<Turkish>5.56 mm 30Rnd Mag (Mk318)</Turkish>
|
<Turkish>5.56 mm 30Rnd Mag (Mk318)</Turkish>
|
||||||
@ -2322,7 +2322,7 @@
|
|||||||
<Portuguese>Carregador 7.62 mm com 10 cartuchos (Mk319 Mod 0)</Portuguese>
|
<Portuguese>Carregador 7.62 mm com 10 cartuchos (Mk319 Mod 0)</Portuguese>
|
||||||
<Hungarian>7,62 mm 10-lövedékes tár (Mk319 Mod 0)</Hungarian>
|
<Hungarian>7,62 mm 10-lövedékes tár (Mk319 Mod 0)</Hungarian>
|
||||||
<Japanese>7.62mm 10Rnd マガジン (Mk319 Mod 0)</Japanese>
|
<Japanese>7.62mm 10Rnd マガジン (Mk319 Mod 0)</Japanese>
|
||||||
<Korean>10발들이 7.62mm 탄창 (Mk.319 Mod 0)</Korean>
|
<Korean>10발 들이 7.62mm 탄창 (Mk.319 Mod 0)</Korean>
|
||||||
<Chinese>7.62毫米 10發 彈匣 (Mk319 Mod 0 特戰專用彈)</Chinese>
|
<Chinese>7.62毫米 10發 彈匣 (Mk319 Mod 0 特戰專用彈)</Chinese>
|
||||||
<Chinesesimp>7.62 mm 10发 弹匣(Mk319 Mod 0)</Chinesesimp>
|
<Chinesesimp>7.62 mm 10发 弹匣(Mk319 Mod 0)</Chinesesimp>
|
||||||
<Turkish>7.62 mm 10Rnd Mag (Mk319 Mod 0)</Turkish>
|
<Turkish>7.62 mm 10Rnd Mag (Mk319 Mod 0)</Turkish>
|
||||||
@ -3344,7 +3344,7 @@
|
|||||||
<Portuguese>Carregador 12.7x99 mm (AMAX) com 5 cartuchos </Portuguese>
|
<Portuguese>Carregador 12.7x99 mm (AMAX) com 5 cartuchos </Portuguese>
|
||||||
<Hungarian>12,7x99 mm 5-lövedékes tár (AMAX)</Hungarian>
|
<Hungarian>12,7x99 mm 5-lövedékes tár (AMAX)</Hungarian>
|
||||||
<Japanese>12.7x99mm 5Rnd マガジン (AMAX)</Japanese>
|
<Japanese>12.7x99mm 5Rnd マガジン (AMAX)</Japanese>
|
||||||
<Korean>5발들이 12.7x99mm 탄창 (AMAX)</Korean>
|
<Korean>5발 들이 12.7x99mm 탄창 (AMAX)</Korean>
|
||||||
<Chinese>12.7x99毫米 5發 彈匣 (AMAX 比賽專用彈)</Chinese>
|
<Chinese>12.7x99毫米 5發 彈匣 (AMAX 比賽專用彈)</Chinese>
|
||||||
<Chinesesimp>12.7x99 mm 5发 弹匣(AMAX)</Chinesesimp>
|
<Chinesesimp>12.7x99 mm 5发 弹匣(AMAX)</Chinesesimp>
|
||||||
<Turkish>12.7x99 mm 5Rnd Şarjör (AMAX)</Turkish>
|
<Turkish>12.7x99 mm 5Rnd Şarjör (AMAX)</Turkish>
|
||||||
@ -3378,7 +3378,7 @@
|
|||||||
<Portuguese>Carregador 12.7x99 mm (AMAX) com 10 cartuchos </Portuguese>
|
<Portuguese>Carregador 12.7x99 mm (AMAX) com 10 cartuchos </Portuguese>
|
||||||
<Hungarian>12,7x99 mm 10-lövedékes tár (AMAX)</Hungarian>
|
<Hungarian>12,7x99 mm 10-lövedékes tár (AMAX)</Hungarian>
|
||||||
<Japanese>12.7x99mm 10Rnd マガジン (AMAX)</Japanese>
|
<Japanese>12.7x99mm 10Rnd マガジン (AMAX)</Japanese>
|
||||||
<Korean>10발들이 12.7x99mm 탄창 (AMAX)</Korean>
|
<Korean>10발 들이 12.7x99mm 탄창 (AMAX)</Korean>
|
||||||
<Chinese>12.7x99毫米 10發 彈匣 (AMAX 比賽專用彈)</Chinese>
|
<Chinese>12.7x99毫米 10發 彈匣 (AMAX 比賽專用彈)</Chinese>
|
||||||
<Chinesesimp>12.7x99 mm 10发 弹匣(AMAX)</Chinesesimp>
|
<Chinesesimp>12.7x99 mm 10发 弹匣(AMAX)</Chinesesimp>
|
||||||
<Turkish>12.7x99 mm 10Rnd Şarjör (AMAX)</Turkish>
|
<Turkish>12.7x99 mm 10Rnd Şarjör (AMAX)</Turkish>
|
||||||
@ -3540,6 +3540,7 @@
|
|||||||
<French>Utilisation de l'IA</French>
|
<French>Utilisation de l'IA</French>
|
||||||
<Portuguese>Utilização por IA</Portuguese>
|
<Portuguese>Utilização por IA</Portuguese>
|
||||||
<Russian>Использование ИИ</Russian>
|
<Russian>Использование ИИ</Russian>
|
||||||
|
<Spanish>Uso de la IA</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Ballistics_ammoUsageShort_illumination">
|
<Key ID="STR_ACE_Ballistics_ammoUsageShort_illumination">
|
||||||
<English>Illum</English>
|
<English>Illum</English>
|
||||||
@ -3551,6 +3552,7 @@
|
|||||||
<French>Fusées éclairantes</French>
|
<French>Fusées éclairantes</French>
|
||||||
<Portuguese>Sinalizadoras</Portuguese>
|
<Portuguese>Sinalizadoras</Portuguese>
|
||||||
<Russian>Осветители</Russian>
|
<Russian>Осветители</Russian>
|
||||||
|
<Spanish>Iluminación</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Ballistics_ammoUsageShort_concealment">
|
<Key ID="STR_ACE_Ballistics_ammoUsageShort_concealment">
|
||||||
<English>Smoke</English>
|
<English>Smoke</English>
|
||||||
@ -3562,6 +3564,7 @@
|
|||||||
<French>Fumigènes</French>
|
<French>Fumigènes</French>
|
||||||
<Portuguese>Fumígenas</Portuguese>
|
<Portuguese>Fumígenas</Portuguese>
|
||||||
<Russian>Дым</Russian>
|
<Russian>Дым</Russian>
|
||||||
|
<Spanish>Humo</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Ballistics_ammoUsageShort_infantry">
|
<Key ID="STR_ACE_Ballistics_ammoUsageShort_infantry">
|
||||||
<English>Inf</English>
|
<English>Inf</English>
|
||||||
@ -3573,6 +3576,7 @@
|
|||||||
<French>Infanterie</French>
|
<French>Infanterie</French>
|
||||||
<Portuguese>Infantaria</Portuguese>
|
<Portuguese>Infantaria</Portuguese>
|
||||||
<Russian>Пехота</Russian>
|
<Russian>Пехота</Russian>
|
||||||
|
<Spanish>Infantería</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Ballistics_ammoUsageShort_lightVehicle">
|
<Key ID="STR_ACE_Ballistics_ammoUsageShort_lightVehicle">
|
||||||
<English>Veh</English>
|
<English>Veh</English>
|
||||||
@ -3584,6 +3588,7 @@
|
|||||||
<French>Véhicule</French>
|
<French>Véhicule</French>
|
||||||
<Portuguese>Veículo</Portuguese>
|
<Portuguese>Veículo</Portuguese>
|
||||||
<Russian>Техника</Russian>
|
<Russian>Техника</Russian>
|
||||||
|
<Spanish>Vehículo</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Ballistics_ammoUsageShort_armor">
|
<Key ID="STR_ACE_Ballistics_ammoUsageShort_armor">
|
||||||
<English>Armor</English>
|
<English>Armor</English>
|
||||||
@ -3595,6 +3600,7 @@
|
|||||||
<French>Blindage</French>
|
<French>Blindage</French>
|
||||||
<Portuguese>Blindagem</Portuguese>
|
<Portuguese>Blindagem</Portuguese>
|
||||||
<Russian>Бронетехника</Russian>
|
<Russian>Бронетехника</Russian>
|
||||||
|
<Spanish>Blindados</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
<Key ID="STR_ACE_Ballistics_ammoUsageShort_aircraft">
|
<Key ID="STR_ACE_Ballistics_ammoUsageShort_aircraft">
|
||||||
<English>Air</English>
|
<English>Air</English>
|
||||||
@ -3606,6 +3612,7 @@
|
|||||||
<French>Aviation</French>
|
<French>Aviation</French>
|
||||||
<Portuguese>Aeronaves</Portuguese>
|
<Portuguese>Aeronaves</Portuguese>
|
||||||
<Russian>Авиация</Russian>
|
<Russian>Авиация</Russian>
|
||||||
|
<Spanish>Aeronaves</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
</Package>
|
</Package>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -24,7 +24,7 @@ if (isServer) then {
|
|||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
["unit", FUNC(handlePlayerChanged)] call CBA_fnc_addPlayerEventHandler;
|
["unit", LINKFUNC(handlePlayerChanged)] call CBA_fnc_addPlayerEventHandler;
|
||||||
[QGVAR(moveInCaptive), LINKFUNC(vehicleCaptiveMoveIn)] call CBA_fnc_addEventHandler;
|
[QGVAR(moveInCaptive), LINKFUNC(vehicleCaptiveMoveIn)] call CBA_fnc_addEventHandler;
|
||||||
[QGVAR(moveOutCaptive), LINKFUNC(vehicleCaptiveMoveOut)] call CBA_fnc_addEventHandler;
|
[QGVAR(moveOutCaptive), LINKFUNC(vehicleCaptiveMoveOut)] call CBA_fnc_addEventHandler;
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ params ["_unit", "_target"];
|
|||||||
|
|
||||||
(_target getVariable [QGVAR(isHandcuffed), false]) &&
|
(_target getVariable [QGVAR(isHandcuffed), false]) &&
|
||||||
{isNull (attachedTo _target)} &&
|
{isNull (attachedTo _target)} &&
|
||||||
{alive _target} &&
|
{_target call EFUNC(common,isAwake)} &&
|
||||||
{!(_target getVariable ["ACE_isUnconscious", false])} &&
|
|
||||||
{(vehicle _unit) == _unit} &&
|
{(vehicle _unit) == _unit} &&
|
||||||
{(vehicle _target) == _target}
|
{(vehicle _target) == _target}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
params ["_unit", "_target", "_vehicle"];
|
params ["_unit", "_target", "_vehicle"];
|
||||||
|
|
||||||
// Don't show "Load Captive" if unit is unconscious (already has "Load Patient")
|
// Don't show "Load Captive" if unit is unconscious (already has "Load Patient")
|
||||||
if (_target getVariable ["ACE_isUnconscious", false]) exitWith {false};
|
if !(_target call EFUNC(common,isAwake)) exitWith {false};
|
||||||
|
|
||||||
if ((isNull _target) && {_unit getVariable [QGVAR(isEscorting), false]}) then {
|
if ((isNull _target) && {_unit getVariable [QGVAR(isEscorting), false]}) then {
|
||||||
//Looking at a vehicle while escorting, get target from attached objects:
|
//Looking at a vehicle while escorting, get target from attached objects:
|
||||||
|
@ -39,12 +39,12 @@ if (_state) then {
|
|||||||
_args params ["_unit", "_target", "_actionID"];
|
_args params ["_unit", "_target", "_actionID"];
|
||||||
|
|
||||||
if (_unit getVariable [QGVAR(isEscorting), false]) then {
|
if (_unit getVariable [QGVAR(isEscorting), false]) then {
|
||||||
if (!alive _target || {!alive _unit} || {!canStand _target} || {!canStand _unit} || {_target getVariable ["ACE_isUnconscious", false]} || {_unit getVariable ["ACE_isUnconscious", false]} || {!isNull (attachedTo _unit)}) then {
|
if (!canStand _target || {!canStand _unit} || {!(_target call EFUNC(common,isAwake))} || {!(_unit call EFUNC(common,isAwake))} || {!isNull (attachedTo _unit)}) then {
|
||||||
_unit setVariable [QGVAR(isEscorting), false, true];
|
_unit setVariable [QGVAR(isEscorting), false, true];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(_unit getVariable [QGVAR(isEscorting), false])) then {
|
if !(_unit getVariable [QGVAR(isEscorting), false]) then {
|
||||||
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
|
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
|
||||||
[objNull, _target, false] call EFUNC(common,claim);
|
[objNull, _target, false] call EFUNC(common,claim);
|
||||||
detach _target;
|
detach _target;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user