Merge branch 'master' into markinglaser

This commit is contained in:
johnb432 2024-07-20 21:20:20 +02:00
commit 4f726d6bc0
4091 changed files with 69648 additions and 70749 deletions

View File

@ -36,7 +36,7 @@ We welcome anyone to contribute to this repository. Issues that we are actively
When contributing to this repository, please first discuss the change you wish to make via issue or [Discord](https://acemod.org/discord) with the [ACE3 project maintainers](https://ace3.acemod.org/team.html) before making a change. This may not be necessary if you are contributing for something which has an existing issue in our repository already.
1. Please make a pull request (PR) as early as possible. This lets use help you in the proces of developing it. When opening a work in progress pull request, mark your PR with a `WIP:` prefix.
1. Please make a pull request (PR) as early as possible. This lets use help you in the proces of developing it. When opening a work in progress pull request, use GitHub's draft feature. This will mark the PR as a work in progress and will prevent it from being merged until you mark it as ready for review.
2. Describe what this pull request will do and how it solves this in the description of your PR. A clear intent and description of the way the issue is resolved will help us to review the PR more efficiently.
3. Please follow our [Development Guidelines](https://ace3.acemod.org/wiki/development/).

View File

@ -23,14 +23,14 @@ All good? Then proceed and fill out the items below.
**Mods (complete and add to the following information):**
- **Arma 3:** `x.xx` [e.g. 1.00 stable, rc, dev]
- **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! -->
**Description:**
A clear and concise description of what the bug is.
**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 ..._
2. _Click ..._

View File

@ -4,6 +4,6 @@
### IMPORTANT
- [ ] If the contribution affects [the documentation](https://github.com/acemod/ACE3/tree/master/docs), please include your changes in this pull request so the documentation will appear on the [website](https://ace3.acemod.org/).
- [ ] [Development Guidelines](https://ace3.acemod.org/wiki/development/) are read, understood and applied.
- [ ] Title of this PR uses our standard template `Component - Add|Fix|Improve|Change|Make|Remove {changes}`.
- If the contribution affects [the documentation](https://github.com/acemod/ACE3/tree/master/docs), please include your changes in this pull request so the documentation will appear on the [website](https://ace3.acemod.org/).
- [Development Guidelines](https://ace3.acemod.org/wiki/development/) are read, understood and applied.
- Title of this PR uses our standard template `Component - Add|Fix|Improve|Change|Make|Remove {changes}`.

View File

@ -5,14 +5,16 @@ branches:
name-template: 'Version $NEXT_PATCH_VERSION'
tag-template: 'v$NEXT_PATCH_VERSION'
sort-by: title # sort alphabetically
sort-direction: ascending
categories:
- title: '**ADDED:**'
labels:
- 'kind/feature request'
- 'kind/added feature'
- 'kind/feature'
- title: '**FIXED:**'
labels:
- 'kind/bug fix'
- 'kind/bug-fix'
- title: '**IMPROVED:**'
labels:
- 'kind/enhancement'
@ -20,13 +22,16 @@ categories:
- title: '**CHANGED:**'
labels:
- 'kind/cleanup'
- 'area/compatibility'
- 'kind/change'
- title: '**SETTINGS:**'
labels:
- 'kind/setting'
- title: '**TRANSLATIONS:**'
labels:
- 'area/translations'
- 'kind/translation'
exclude-labels:
- 'ignore changelog'
- 'ignore-changelog'
- 'dependencies'
change-template: '- $TITLE (#$NUMBER)'
@ -39,5 +44,5 @@ template: |
replacers:
# Category titles
- search: '/\#\# (\*\*(ADDED|FIXED|IMPROVED|CHANGED|TRANSLATIONS):\*\*)/g'
- search: '/\#\# (\*\*(ADDED|FIXED|IMPROVED|CHANGED|SETTINGS|TRANSLATIONS):\*\*)/g'
replace: '$1'

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the source code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Validate SQF
run: python3 tools/sqf_validator.py
- name: Validate Config
@ -22,6 +22,8 @@ jobs:
run: python3 tools/check_strings.py
- name: Check for BOM
uses: arma-actions/bom-check@master
with:
path: 'addons'
- name: Validate function headers
run: python3 docs/tools/document_functions.py --debug
@ -29,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the source code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Lint (sqflint)
uses: arma-actions/sqflint@master
continue-on-error: true # No failure due to many false-positives
@ -38,7 +40,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the source code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup HEMTT
uses: arma-actions/hemtt@v1
- name: Run HEMTT build
@ -46,7 +48,7 @@ jobs:
- name: Rename build folder
run: mv .hemttout/build .hemttout/@ace
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ace3-${{ github.sha }}-nobin
path: .hemttout/@*

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the source code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Python packages
run: |
pip3 install wheel
@ -33,7 +33,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Extract Dependencies
run: python3 tools/extract_dependencies.py --markdown
@ -47,7 +47,7 @@ jobs:
destination: docs/_site/
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: jekyll-site
path: docs/_site/
@ -63,7 +63,7 @@ jobs:
steps:
- name: Download Artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: jekyll-site
path: _site/

View File

@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout the source code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Build
shell: cmd
run: |
@ -23,7 +23,7 @@ jobs:
cd build
cmake .. && cmake --build .
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ace3_extensions-${{ matrix.os }}-debug
path: extensions/build

44
.github/workflows/hemtt.yml vendored Normal file
View File

@ -0,0 +1,44 @@
name: HEMTT
on:
push:
branches:
- master
pull_request_target:
jobs:
windows:
runs-on: windows-latest
steps:
- name: Install Arma 3 Tools
uses: arma-actions/arma3-tools@master
with:
toolsUrl: ${{ secrets.ARMA3_TOOLS_URL }}
- name: Checkout the source code
uses: actions/checkout@v4
- name: Setup HEMTT
uses: arma-actions/hemtt@v1
- name: Checkout pull request
uses: actions/checkout@v4
if: ${{ github.event_name == 'pull_request_target' }}
with:
path: pullrequest
ref: 'refs/pull/${{ github.event.number }}/merge'
- name: Replace addons with pull request addons
if: ${{ github.event_name == 'pull_request_target' }}
run: |
rm -r addons\
rm -r optionals\
rm -r include\
xcopy /e /h /q pullrequest\addons addons\
xcopy /e /h /q pullrequest\optionals optionals\
xcopy /e /h /q pullrequest\include include\
- name: Run HEMTT build
run: hemtt build
- name: Rename build folder
run: mv .hemttout/build .hemttout/@ace
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ace3-${{ github.sha }}
path: .hemttout/@*

View File

@ -25,7 +25,7 @@ jobs:
Invoke-WebRequest "$env:RHSUSF_URL" -OutFile rhsusf.zip
$files = @("arma3.zip", "rhsafrf.zip", "rhsgref.zip", "rhssaf.zip", "rhsusf.zip")
ForEach ($file in $files) {
Extract-7Zip -Path $file -DestinationPath .
Expand-7ZipArchive -Path $file -DestinationPath .
Remove-Item $file
}
env:
@ -35,18 +35,18 @@ jobs:
RHSSAF_URL: ${{ secrets.RHSSAF_URL }}
RHSUSF_URL: ${{ secrets.RHSUSF_URL }}
- name: Checkout CBA A3
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: x\cba
ref: master
repository: CBATeam/CBA_A3.git
- name: Checkout ACE3
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: z\ace
persist-credentials: false
- name: Checkout pull request
uses: actions/checkout@v3
uses: actions/checkout@v4
if: ${{ github.event_name == 'pull_request_target' }}
with:
path: pullrequest
@ -64,21 +64,22 @@ jobs:
run: |
subst P: .
pboproject -P
xcopy /e /h /q z\ace\tools\pDummies\A3\ui_f_enoch a3\ui_f_enoch\
xcopy /e /h /q z\ace\tools\pDummies\gm gm\
xcopy /e /h /q z\ace\tools\pDummies\vn vn\
xcopy /e /h /q z\ace\tools\pDummies\WW2 WW2\
xcopy /e /h /q z\ace\tools\pDummies\CUP CUP\
- name: Build
run: py P:\z\ace\tools\make.py ci
env:
PYTHONUNBUFFERED: 1
- name: Archive logs
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: logs
path: temp/*.log
- name: Archive @ace
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: '@ace3-${{ github.sha }}'
path: z\ace\release\@ace

View File

@ -11,6 +11,6 @@ jobs:
steps:
- name: Release Drafter
if: github.repository == 'acemod/ACE3'
uses: release-drafter/release-drafter@v5
uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ CHANGELOG.md
sqfvm.exe
ArmaScriptCompiler.exe
*.sqfc
!extras/**/*.zip

View File

@ -0,0 +1,4 @@
let docs_readmes = ["README.zh-TW.md", "README_DE.md", "README_PL.md"];
for readme in docs_readmes {
HEMTT_VFS.join("docs").join(readme).move(HEMTT_VFS.join(readme));
}

View File

@ -0,0 +1,9 @@
let releases = HEMTT_RFS.join("releases");
let src = releases.join(HEMTT.project().prefix() + "-" + HEMTT.project().version().to_string() + ".zip");
let dst = releases.join(HEMTT.project().name().to_lower() + "_" + HEMTT.project().version().to_string_short() + ".zip");
print("Moving zip to " + dst);
if !src.move(dst) {
fatal("Failed to move " + src + " to " + dst);
}

View File

@ -0,0 +1,12 @@
let modcpp = HEMTT_VFS.join("mod.cpp").open_file().read();
modcpp.replace("0.0.0", HEMTT.project().version().to_string_short());
HEMTT_VFS.join("mod.cpp").create_file().write(modcpp);
print("mod.cpp version set");
let docs_readmes = ["README.zh-TW.md", "README_DE.md", "README_PL.md"];
for readme in docs_readmes {
let readmemd = HEMTT_VFS.join("docs").join(readme).open_file().read();
readmemd.replace("0.0.0", HEMTT.project().version().to_string_short());
HEMTT_VFS.join("docs").join(readme).create_file().write(readmemd);
print(readme + " version set");
}

View File

@ -8,8 +8,7 @@ include = [
"*.dll",
"*.so",
"mod.cpp",
"README.md",
"docs/README_*.md",
"README*.md", # Translated READMEs get moved to root in a hook (virtual file system)
"AUTHORS.txt",
"LICENSE",
"logo_ace3_ca.paa",
@ -19,21 +18,50 @@ include = [
[version]
git_hash = 0
# Unused in HEMTT v1.11 or higher, kept for backwards compatibility
[asc]
enabled = true
exclude = [
"/initsettings.sqf",
"/initkeybinds.sqf",
"/xeh_prep.sqf",
"dev",
"medical_ai/statemachine.sqf",
".inc.sqf",
"/dev/",
"common/functions/fnc_dummy.sqf",
"zeus/functions/fnc_zeusAttributes.sqf",
]
[hemtt.config]
preset = "Hemtt"
[hemtt.launch.default]
workshop = [
"450814997", # CBA_A3
]
[hemtt.launch]
[hemtt.launch.spe]
workshop = [
"450814997", # CBA_A3
]
dlc = [
"spe"
]
[hemtt.launch.vn]
workshop = [
"450814997", # CBA_A3's Workshop ID
]
dlc = [
"S.O.G. Prairie Fire",
]
[hemtt.launch.ws]
workshop = [
"450814997", # CBA_A3's Workshop ID
]
dlc = [
"Western Sahara",
]
[hemtt.launch.rhs]
workshop = [
"450814997", # CBA_A3's Workshop ID
"843425103", # RHS AFRF Workshop ID
"843577117", # RHS USAF Workshop ID
"843593391", # RHS GREF Workshop ID
"843632231", # RHS SAF Workshop ID
]

View File

@ -6,24 +6,31 @@
# request, preferably including an email address.
# CORE TEAM
BaerMitUmlaut
Brett Mayson
bux578 <github@jonathandavid.de>
commy2
Dahlgren
Dani (TCVM) <baileydanyluk@gmail.com>
Drofseh <drofseh.arma@gmail.com>
esteldunedain <nicolas.d.badano@gmail.com>
Felix Wiegand <koffeinflummi@gmail.com>
Garth "L-H" de Wet <garthofhearts@gmail.com>
Giallustio
Glowbal
Grim
Janus
johnb43
jokoho482 <jokoho482@gmail.com>
Jonpas <jonpas33@gmail.com>
Kieran
kymckay
mharis001 <mhariszakar@gmail.com>
MikeMF
MiszczuZPolski
NouberNou
PabstMirror <pabstmirror@gmail.com>
Ruthberg <ulteq@web.de>
SilentSpike <SilentSpike100@gmail.com>
tcvm <baileydanyluk@gmail.com>
tpM
veteran29
ViperMaul
@ -42,6 +49,7 @@ aeroson
Aggr094 <bastards4glory@gmail.com>
alef <alefor@gmail.com>
Aleksey EpMAK Yermakov <epmak777@gmail.com>
AleM
Alganthe <alganthe@live.fr>
Andrea "AtixNeon" Verano <veranoandrea88@gmail.com>
Anthariel <Contact@storm-simulation.com>
@ -50,14 +58,12 @@ Arcanum417 <lubos.len@gmail.com>
Arkhir <wonsz666@gmail.com >
ARV187 aka Spark23
Asgar Serran <piechottaf@web.de>
BaerMitUmlaut
Bamse <bamsis@gmail.com>
Barman75
Bla1337
BlackPixxel <blackpixxel96@gmail.com>
BlackQwar
Brakoviejo
Brett Mayson
Brisse <brisse@outlook.com>
Brostrom.A | Evul <andreas.brostrom.ce@gmail.com>
BullHorn <bullhorn7@gmail.com>
@ -77,7 +83,6 @@ diwako
dixon13 <dixonbegay@gmail.com>
Drift_91
Drill <drill87@gmail.com>
Drofseh <drofseh@gmail.com>
Dslyecxi <dslyecxi@gmail.com>
Dudakov aka [OMCB]Kaban <dudakov.s@gmail.com>
Eclipser <jms@modeemi.fi>
@ -111,7 +116,9 @@ havena <silveredenis@gmail.com>
Hawkins
Head <brobergsebastian@gmail.com>
Hybrid V
Hypoxic <martini_a@outlook.com>
JasperRab <jasper@jasperrab.eu>
JDT
john681611 <john681611@hotmail.com>
JoramD
Karneck <dschultz26@hotmail.com>
@ -119,6 +126,8 @@ Kavinsky <nmunozfernandez@gmail.com>
Keithen <Keithen.Neu@gmail.com>
Kllrt <kllrtik@gmail.com>
KokaKolaA3
Krzyciu
LAxemann
legman <juicemelon@msn.com>
Legolasindar "Viper" <legolasindar@gmail.com>
licht-im-Norden87 <lichtimnorden87@gmail.com>
@ -173,7 +182,6 @@ Toaster <jonathan.pereira@gmail.com>
Tonic
Tourorist <tourorist@gmail.com>
Tuupertunut
TyroneMF <TyroneMF@hotmail.com>
Valentin Torikian <valentin.torikian@gmail.com>
voiper
VyMajoris(W-Cephei)<vycanismajoriscsa@gmail.com>
@ -183,4 +191,5 @@ wizpig64
YetheSamartaka
xrufix
Zakant <Zakant@gmx.de>
zGuba
zGuba
Zman6258

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

View File

@ -1,10 +1,11 @@
<p align="center">
<img src="https://github.com/acemod/ACE3/raw/master/extras/assets/logo/black/ACE3-Logo.jpg" width="480">
<img src="https://github.com/acemod/ACE3/raw/master/extras/assets/logo/black/ACE3-Logo.png#gh-light-mode-only" width="480">
<img src="https://github.com/acemod/ACE3/raw/master/extras/assets/logo/white/ACE3-Logo.png#gh-dark-mode-only" width="480">
</p>
<p align="center">
<a href="https://github.com/acemod/ACE3/releases/latest">
<img src="https://img.shields.io/badge/Version-3.15.2-blue.svg?style=flat-square" alt="ACE3 Version">
<img src="https://img.shields.io/github/release/acemod/ACE3.svg?style=flat-square&label=Version" alt="ACE3 Version">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?style=flat-square&label=Issues" alt="ACE3 Issues">
@ -21,9 +22,6 @@
<a href="https://acemod.org/discord">
<img src="https://img.shields.io/badge/Discord-Join-darkviolet.svg?style=flat-square" alt="ACE3 Discord">
</a>
<a href="https://circleci.com/gh/acemod/ACE3">
<img src="https://circleci.com/gh/acemod/ACE3.svg?style=svg" alt="ACE3 Build Status">
</a>
</p>
<p align="center">
@ -97,9 +95,7 @@ Please, use our [Issue Tracker](https://github.com/acemod/ACE3/issues) to report
### Testing & building
To help us test the latest development changes, download our master branch ([directly](https://github.com/acemod/ACE3/archive/master.zip), or [with git](https://help.github.com/articles/fetching-a-remote/)), then assemble a test build:
- [Setting up the development environment](https://ace3.acemod.org/wiki/development/setting-up-the-development-environment.html) step-by-step instructions on how to properly setup and build a version of ACE3 for testing purposes.
To help us test the latest development changes, download the [artifact](https://github.com/acemod/ACE3/actions/workflows/arma.yml) of the branch you'd like to test or subscribe to "Anrop ACE3 Master" on the workshop to test `master` branch. Alternatively [build your own version](https://ace3.acemod.org/wiki/development/setting-up-the-development-environment.html).
### Get in touch

View File

@ -1,7 +1,5 @@
#include "script_component.hpp"
#include "initKeybinds.sqf"
GVAR(currentbulletID) = -1;
GVAR(Protractor) = false;
@ -11,6 +9,8 @@ GVAR(currentGrid) = 0;
if (!hasInterface) exitWith {};
#include "initKeybinds.inc.sqf"
["CBA_settingsInitialized", {
//If not enabled, dont't add PFEH
if (!GVAR(enabled)) exitWith {};
@ -19,11 +19,11 @@ if (!hasInterface) exitWith {};
[] call FUNC(initializeTerrainExtension);
// Register fire event handler
["ace_firedPlayer", DFUNC(handleFired)] call CBA_fnc_addEventHandler;
["ace_firedPlayerNonLocal", DFUNC(handleFired)] call CBA_fnc_addEventHandler;
["ace_firedPlayer", LINKFUNC(handleFired)] call CBA_fnc_addEventHandler;
["ace_firedPlayerNonLocal", LINKFUNC(handleFired)] call CBA_fnc_addEventHandler;
// Register Perframe Handler
[FUNC(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)
{

View File

@ -6,6 +6,6 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
#include "initSettings.sqf"
#include "initSettings.inc.sqf"
ADDON = true;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg, MikeMatrix, joko // Jonas
*

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*

View File

@ -1,5 +1,5 @@
#define DEBUG_MODE_FULL
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: esteldunedain
*

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Glowbal, Ruthberg, joko // Jonas
* Handle the PFH for Bullets

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Glowbal, Ruthberg
*
@ -17,9 +17,9 @@
*/
//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 (underwater _unit) exitWith {};

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Glowbal, Ruthberg
* Module for adjusting the advanced ballistics settings

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
* Initializes the advanced ballistics extension with terrain data
@ -19,10 +19,10 @@ if (!hasInterface) exitWith {};
if (!GVAR(enabled)) exitWith {};
private _initStartTime = diag_tickTime;
private _mapSize = getNumber (configFile >> "CfgWorlds" >> worldName >> "MapSize");
private _mapSize = worldSize;
if (("ace_advanced_ballistics" callExtension format["init:%1:%2", worldName, _mapSize]) == "Terrain already initialized") exitWith {
INFO_1("Terrain already initialized [world: %1]", worldName);
INFO_1("Terrain already initialized [world: %1]",worldName);
#ifdef DEBUG_MODE_FULL
systemChat "AdvancedBallistics: Terrain already initialized";
#endif
@ -33,14 +33,14 @@ private _gridCells = _mapGrids * _mapGrids;
GVAR(currentGrid) = 0;
INFO_2("Starting Terrain Extension [cells: %1] [world: %2]", _gridCells, worldName);
INFO_2("Starting Terrain Extension [cells: %1] [world: %2]",_gridCells,worldName);
[{
params ["_args","_idPFH"];
_args params ["_mapGrids", "_gridCells", "_initStartTime"];
if (GVAR(currentGrid) >= _gridCells) exitWith {
INFO_2("Finished terrain initialization in %1 seconds [world: %2]", (diag_tickTime - _initStartTime) toFixed 2, worldName);
INFO_2("Finished terrain initialization in %1 seconds [world: %2]",(diag_tickTime - _initStartTime) toFixed 2,worldName);
#ifdef DEBUG_MODE_FULL
systemChat format["AdvancedBallistics: Finished terrain initialization in %1 seconds", (diag_tickTime - _initStartTime) toFixed 2];
#endif
@ -53,7 +53,7 @@ INFO_2("Starting Terrain Extension [cells: %1] [world: %2]", _gridCells, worldNa
private _gridCenter = [_x + 25, _y + 25];
private _gridHeight = round(getTerrainHeightASL _gridCenter);
private _gridNumObjects = count (_gridCenter nearObjects ["Building", 50]);
private _gridSurfaceIsWater = if (surfaceIsWater _gridCenter) then {1} else {0};
private _gridSurfaceIsWater = parseNumber (surfaceIsWater _gridCenter);
"ace_advanced_ballistics" callExtension format["set:%1:%2:%3", _gridHeight, _gridNumObjects, _gridSurfaceIsWater];
GVAR(currentGrid) = GVAR(currentGrid) + 1;
if (GVAR(currentGrid) >= _gridCells) exitWith {};

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*
@ -40,10 +40,13 @@ if (_transonicStabilityCoef == 0) then {
_transonicStabilityCoef = 0.5;
};
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;
};
private _ballisticCoefficients = getArray(_ammoConfig >> "ACE_ballisticCoefficients");
if (_ballisticCoefficients isEqualTo []) then {
_ballisticCoefficients = [0.5];
};
private _velocityBoundaries = getArray(_ammoConfig >> "ACE_velocityBoundaries");
private _atmosphereModel = getText(_ammoConfig >> "ACE_standardAtmosphere");
if (_atmosphereModel isEqualTo "") then {
@ -66,7 +69,7 @@ if ((_typicalSpeed > 0) && {_typicalSpeed < 360}) then {
if (_inheritedBarrelConfig || _inheritedTempConfig) then {
private _parentConfig = inheritsFrom _ammoConfig;
private _parentSpeed = getNumber (_parentConfig >> "typicalSpeed");
WARNING_4("Subsonic Ammo %1 (%2 m/s) missing `ACE_muzzleVelocities` or `ACE_ammoTempMuzzleVelocityShifts` configs, attempting to use parent %3 (%4m/s)",_this,_typicalSpeed,configName _parentConfig, _parentSpeed);
WARNING_4("Subsonic Ammo %1 (%2 m/s) missing `ACE_muzzleVelocities` or `ACE_ammoTempMuzzleVelocityShifts` configs, attempting to use parent %3 (%4m/s)",_this,_typicalSpeed,configName _parentConfig,_parentSpeed);
if (_parentSpeed <= 0) exitWith {//Handle weird or null parent
_muzzleVelocityTable = [];
_ammoTempMuzzleVelocityShifts = [];

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Ruthberg
*
@ -21,7 +21,7 @@
private _weaponConfig = (configFile >> "CfgWeapons" >> _this);
private _barrelTwist = 0 max getNumber(_weaponConfig >> "ACE_barrelTwist");
private _twistDirection = [0, 1] select (_barrelTwist != 0);
private _twistDirection = parseNumber (_barrelTwist != 0);
if (isNumber (_weaponConfig >> "ACE_twistDirection")) then {
_twistDirection = getNumber (_weaponConfig >> "ACE_twistDirection");
if !(_twistDirection in [-1, 0, 1]) then {

View File

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

View File

@ -4,7 +4,7 @@
<Key ID="STR_ACE_Advanced_Ballistics_WindInfoKey">
<English>Show Wind Info</English>
<Polish>Pokaż inf. o wietrze</Polish>
<Italian>Mostra indicazioni del vento</Italian>
<Italian>Mostra indicazioni vento</Italian>
<Russian>Показать информацию о ветре</Russian>
<French>Afficher les infos sur le vent</French>
<Spanish>Mostrar información del viento</Spanish>
@ -46,7 +46,7 @@
<Hungarian>Fejlett ballisztika</Hungarian>
<Russian>Продвинутая баллистика</Russian>
<Italian>Balistica Avanzata</Italian>
<Japanese>アドバンスド バリスティックス</Japanese>
<Japanese>アドバンスド弾道計算</Japanese>
<Korean>고급 탄도학</Korean>
<Chinese>先進彈道系統</Chinese>
<Chinesesimp>进阶弹道系统</Chinesesimp>
@ -63,7 +63,7 @@
<Hungarian>Fejlett ballisztika</Hungarian>
<Russian>Продвинутая баллистика</Russian>
<Italian>Balistica Avanzata</Italian>
<Japanese>アドバンスド バリスティックスを有効化</Japanese>
<Japanese>アドバンスド弾道計算を有効化</Japanese>
<Korean>고급 탄도학</Korean>
<Chinese>先進彈道系統</Chinese>
<Chinesesimp>进阶弹道系统</Chinesesimp>
@ -80,7 +80,7 @@
<Hungarian>Engedélyezi a fejlett ballisztikát</Hungarian>
<Russian>Включает продвинутую баллистику</Russian>
<Italian>Abilita Balistica Avanzata</Italian>
<Japanese>アドバンスド バリスティックスを有効化します。</Japanese>
<Japanese>アドバンスド弾道計算は高度な弾道計算処理を有効化します。</Japanese>
<Korean>고급 탄도학을 적용합니다</Korean>
<Chinese>啟用先進彈道系統</Chinese>
<Chinesesimp>启用进阶弹道系统</Chinesesimp>
@ -106,8 +106,8 @@
<English>Simulates slight variations in muzzle velocity between each shot</English>
<Spanish>Simula variaciones ligeras de velocidad entre cada disparo</Spanish>
<German>Simuliert leichte Variationen der Mündungsgeschwindigkeit zwischen jedem Schuss.</German>
<Japanese>発射毎の銃口初速の変動をシミュレートします。</Japanese>
<Italian>Simula lievi variazioni della velocità della volata tra un colpo e l'altro</Italian>
<Japanese>発射毎の銃口初速のわずかな変動をシミュレートします。</Japanese>
<Italian>Simula piccole variazioni della velocità alla volata tra ogni colpo.</Italian>
<Korean>각 사격 사이에 총구속도 변화를 시뮬레이션 합니다.</Korean>
<Chinese>模擬每發子彈的槍口初速都略有不同</Chinese>
<Chinesesimp>模拟每发子弹的枪口初速都略有不同</Chinesesimp>
@ -128,8 +128,8 @@
<French>Activer la simulation de la température</French>
<Hungarian>Lőszer-hő szimuláció engedélyezése</Hungarian>
<Russian>Симуляция температуры для боеприпасов</Russian>
<Italian>Abilita simulazione della temperatura delle munizioni</Italian>
<Japanese>弾薬温度シミュレーションを有効化</Japanese>
<Italian>Abilita simulazione temperatura munizioni</Italian>
<Japanese>弾薬温度シミュレーションを有効化</Japanese>
<Korean>탄약 온도 구현 적용</Korean>
<Chinese>啟用彈藥溫度模擬系統</Chinese>
<Chinesesimp>启用弹药温度模拟系统</Chinesesimp>
@ -145,7 +145,7 @@
<French>La vitesse initiale varie en fonction de la température des munitions.</French>
<Hungarian>A kezdősebesség a lőszer hőmérsékletétől függően változó</Hungarian>
<Russian>Начальная скорость пули зависит от температуры</Russian>
<Italian>La velocità dello sparo varia a seconda della temperatura delle munizioni</Italian>
<Italian>La velocità alla volata varia a seconda della temperatura delle munizioni.</Italian>
<Japanese>弾薬の温度により銃口初速を変動させます。</Japanese>
<Korean>탄약 온도에 비례해 총구 속도가 달라집니다</Korean>
<Chinese>子彈初速將隨彈藥溫度而有所變化</Chinese>
@ -162,8 +162,8 @@
<French>Activer la simulation de la longueur de canon</French>
<Hungarian>Csőhossz-szimuláció engedélyezése</Hungarian>
<Russian>Симуляция длины ствола</Russian>
<Italian>Abilita simulazione della lunghezza della canna</Italian>
<Japanese>銃身長シミュレーションを有効化</Japanese>
<Italian>Abilita simulazione lunghezza canna</Italian>
<Japanese>銃身長シミュレーションを有効化</Japanese>
<Korean>총열 길이 구현 적용</Korean>
<Chinese>啟用槍管長度模擬系統</Chinese>
<Chinesesimp>启用枪管长度模拟系统</Chinesesimp>
@ -179,7 +179,7 @@
<French>La vitesse initiale varie en fonction de la longueur du canon.</French>
<Hungarian>A kezdősebesség a cső hosszától függően változó</Hungarian>
<Russian>Начальная скорость пули зависит от длины ствола</Russian>
<Italian>La velocità di sparo varia a seconda della lunghezza della canna</Italian>
<Italian>La velocità alla volata varia a seconda della lunghezza della canna.</Italian>
<Japanese>銃身長により銃口初速を変動させます。</Japanese>
<Korean>총구 속도가 총열에 비례해 달라집니다</Korean>
<Chinese>子彈初速將隨槍管長度而有所變化</Chinese>
@ -196,7 +196,7 @@
<French>Activer l'effet de balle traçante</French>
<Hungarian>Nyomkövető-effekt engedélyezése</Hungarian>
<Russian>Следы пуль</Russian>
<Italian>Abilita effetto dei Proiettili Traccianti</Italian>
<Italian>Abilita effetto di traccia proiettile</Italian>
<Japanese>弾丸の軌跡エフェクトを有効化</Japanese>
<Korean>예광탄 효과 적용</Korean>
<Chinese>啟用曳光彈效果</Chinese>
@ -213,7 +213,7 @@
<French>Active un effet de balle traçante pour les munitions de gros calibre (seulement visible en utilisant une optique à fort grossissement).</French>
<Hungarian>Engedélyezi a nagy kaliberű lövedékek nyomának vizuális követését (csak nagy teljesítményű optikán keresztül látható)</Hungarian>
<Russian>Включает эффект следов пуль для больших калибров (видны только через мощную оптику)</Russian>
<Italian>Abilita effetto dei proiettili traccianti di alto calibro (visibile solo attraverso ottiche ad alto potenziale)</Italian>
<Italian>Abilita effetto di traccia lasciata da proiettili di alto calibro (visibile solo attraverso ottiche ad alto ingrandimento)</Italian>
<Japanese>大口径弾の軌跡エフェクトを有効化します。 (高性能光学機器を介してのみ見ることができます)</Japanese>
<Korean>대구경 탄환에 예광탄 효과를 적용합니다(오직 고성능 조준경 사용시에만 보입니다)</Korean>
<Chinese>啟用曳光彈效果給大口徑子彈 (只有透過高倍率光學瞄鏡才能看到)</Chinese>
@ -230,7 +230,7 @@
<French>Intervalle de simulation</French>
<Hungarian>Szimuláció intervalluma</Hungarian>
<Russian>Интервал симуляции</Russian>
<Italian>Intervallo Simulazione</Italian>
<Italian>Intervallo di Simulazione</Italian>
<Japanese>シミュレーション間隔</Japanese>
<Korean>구현 간격</Korean>
<Chinese>模擬間隔</Chinese>
@ -246,7 +246,7 @@
<French>Définit l'intervalle entre chacune des étapes de calcul.</French>
<Hungarian>Meghatározza a számítási lépések közötti időintervallumot</Hungarian>
<Russian>Определяет временной интервал между вычислениями</Russian>
<Italian>Definisce l'intervallo tra ogni step di calcolo</Italian>
<Italian>Definisce l'intervallo tra ogni passo del calcolo</Italian>
<Japanese>各シミュレーション毎の間隔を定義します。</Japanese>
<Korean>각 계산 단위의 간격을 정의합니다</Korean>
<Chinese>定義每個模擬計算之間的時間間隔</Chinese>
@ -263,7 +263,7 @@
<Hungarian>Szimuláció hatóköre</Hungarian>
<Russian>Радиус симуляции</Russian>
<Italian>Raggio Simulazione</Italian>
<Japanese>シミュレーションの範囲</Japanese>
<Japanese>シミュレーションの半径</Japanese>
<Korean>구현 범위</Korean>
<Chinese>模擬半徑</Chinese>
<Chinesesimp>模拟半径</Chinesesimp>
@ -279,8 +279,8 @@
<French>Définit le rayon autour du joueur (en mètres), dans lequel la balistique avancée est appliquée aux projectiles.</French>
<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>
<Italian>Definisce il raggio attorno al giocatore (in metri) per cui la Balistica Avanzata è applicata ai proiettili</Italian>
<Japanese>アドバンスド バリスティックスの適用半径範囲 (プレイヤー中心、メートル単位) を定義します。</Japanese>
<Italian>Definisce il raggio attorno al giocatore (in metri) entro il quale la Balistica Avanzata è applicata ai proiettili</Italian>
<Japanese>アドバンスド弾道計算の適用半径範囲 (プレイヤー中心、メートル単位) を定義します。</Japanese>
<Korean>플레이어 주위의 발사체를 고급 탄도학으로 정의하는 범위를 정합니다(미터)</Korean>
<Chinese>以玩家的半徑距離(公尺)定義先進彈道系統啟用範圍</Chinese>
<Chinesesimp>定义玩家周围的半径(米),在这个半径内,进阶弹道系统会被启用</Chinesesimp>
@ -296,8 +296,8 @@
<Hungarian>Ez a modul engedélyezi a fejlett ballisztikai szimulációt - a lövedékek röppályáját befolyásolni fogja a levegő hőmérséklete, légnyomás, páratartalom, gravitáció, a lövedék fajtája, valamint a fegyver, amiből kilőtték a lövedéket.</Hungarian>
<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>
<Italian>Questo modulo abilita la simulazione della Balistica Avanzata - cioè 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>
<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>
<Korean>이 모듈은 고급 탄도학을 적용시킵니다 - 이는 발사체의 궤적이 기온, 대기압, 습도, 중력, 탄환의 종류와 어느 무기에서 발사되는지에 따라 영향을 받습니다.</Korean>
<Chinese>該模塊實現先進的彈道仿真 - 這意味著子彈的軌跡是由空氣溫度、大氣壓力、濕度、重力、彈藥類型以及射擊的武器所影響</Chinese>
<Chinesesimp>该模块实现增强的弹道模拟—子弹的轨迹由空气温度、大气压力、湿度、重力、弹药类型和射击的武器等变量所影响</Chinesesimp>

View File

@ -2,9 +2,11 @@ PREP(addDutyFactor);
PREP(createStaminaBar);
PREP(getAnimDuty);
PREP(getMetabolicCosts);
PREP(getWeaponInertia);
PREP(handleEffects);
PREP(handlePlayerChanged);
PREP(handleStaminaBar);
PREP(mainLoop);
PREP(moduleSettings);
PREP(removeDutyFactor);
PREP(renderDebugLines);

View File

@ -2,26 +2,33 @@
if (!hasInterface) exitWith {};
[missionNamespace, "ACE_setCustomAimCoef", QUOTE(ADDON), {
private _unit = ACE_player;
private _fatigue = _unit getVariable [QGVAR(aimFatigue), 0];
#ifdef DEBUG_MODE_FULL
call FUNC(renderDebugLines);
#endif
switch (stance _unit) do {
case ("CROUCH"): {
(1.0 + _fatigue ^ 2 * 0.1) * GVAR(swayFactor)
};
case ("PRONE"): {
(1.0 + _fatigue ^ 2 * 2.0) * GVAR(swayFactor)
};
default {
(1.5 + _fatigue ^ 2 * 3.0) * GVAR(swayFactor)
};
};
}] call EFUNC(common,arithmeticSetSource);
// recheck weapon inertia after weapon swap, change of attachments or switching unit
["weapon", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
["loadout", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
["unit", {[ACE_player] call FUNC(getWeaponInertia)}, true] call CBA_fnc_addPlayerEventHandler;
["CBA_settingsInitialized", {
if (!GVAR(enabled)) exitWith {};
["baseline", {
private _fatigue = ACE_player getVariable [QGVAR(aimFatigue), 0];
switch (stance ACE_player) do {
case ("CROUCH"): {
(1.0 + _fatigue ^ 2 * 0.1)
};
case ("PRONE"): {
(1.0 + _fatigue ^ 2 * 2.0)
};
default {
(1.5 + _fatigue ^ 2 * 3.0)
};
};
}, QUOTE(ADDON)] call EFUNC(common,addSwayFactor);
// - Post process effect ------------------------------------------------------
GVAR(ppeBlackout) = ppEffectCreate ["ColorCorrections", 4220];
GVAR(ppeBlackout) ppEffectEnable true;
@ -30,28 +37,26 @@ if (!hasInterface) exitWith {};
GVAR(ppeBlackout) ppEffectCommit 0.4;
// - GVAR updating and initialization -----------------------------------------
["unit", LINKFUNC(handlePlayerChanged), true] call CBA_fnc_addPlayerEventHandler;
["unit", LINKFUNC(handlePlayerChanged)] call CBA_fnc_addPlayerEventHandler;
["visibleMap", {
params ["", "_visibleMap"]; // command visibleMap is updated one frame later
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlShow ((!_visibleMap) && {(vehicle ACE_player) == ACE_player});
(uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull]) ctrlShow (!_visibleMap && isNull objectParent ACE_player);
}, true] call CBA_fnc_addPlayerEventHandler;
["vehicle", {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlShow ((!visibleMap) && {(vehicle ACE_player) == ACE_player});
(uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull]) ctrlShow (!visibleMap && isNull objectParent ACE_player);
}, true] call CBA_fnc_addPlayerEventHandler;
// - Duty factors -------------------------------------------------------------
if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then {
if (GETEGVAR(medical,enabled,false)) then {
[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);
[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);
};
if (["ACE_Dragging"] call EFUNC(common,isModLoaded)) then {
if (["ace_dragging"] call EFUNC(common,isModLoaded)) then {
[QEGVAR(dragging,isCarrying), {
[1, 3] select (_this getVariable [QEGVAR(dragging,isCarrying), false]);
}] call FUNC(addDutyFactor);
@ -59,7 +64,7 @@ if (!hasInterface) exitWith {};
// Weather has an off switch, Dragging & Medical don't.
if (missionNamespace getVariable [QEGVAR(weather,enabled), false]) then {
[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);
};

View File

@ -6,10 +6,12 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
#include "initSettings.sqf"
#include "initSettings.inc.sqf"
GVAR(staminaBarWidth) = 10 * (((safezoneW / safezoneH) min 1.2) / 40);
GVAR(dutyList) = createHashMap;
GVAR(setAnimExclusions) = [];
GVAR(inertia) = 0;
GVAR(inertiaCache) = createHashMap;
ADDON = true;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Adds a duty factor.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Creates the stamina bar.

View File

@ -1,7 +1,7 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Calculates the duty of the current animation.
* Calculates the duty ('postureWeight') of the current animation.
*
* Arguments:
* 0: Unit <OBJECT>
@ -37,13 +37,14 @@ if (_animType in ["idl", "mov", "adj"]) then {
};
};
if (currentWeapon _unit != handgunWeapon _unit) then {
if (currentWeapon _unit != "") then {
if (_animName select [13, 3] == "ras") then {
// low ready jog
_duty = _duty * 1.2;
if (_animName select [9, 3] == "tac") then {
// high ready jog/walk
_duty = _duty * 1.5;
_duty = _duty * (1 + 0.8*GVAR(inertia));
} else {
// low ready jog
_duty = _duty * (1 + 0.2*GVAR(inertia));
};
};
};

View File

@ -1,51 +1,74 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Calculates the current metabolic costs for a unit.
* Author: BaerMitUmlaut, ulteq
* Calculates the current metabolic costs.
* Calculation is done according to the Pandolf/Wojtowicz formulas.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Speed <NUMBER>
* 0: Duty of animation
* 1: Mass of unit <NUMBER>
* 2: Terrain gradient <NUMBER>
* 3: Terrain factor <NUMBER>
* 4: Speed <NUMBER>
*
* Return Value:
* Metabolic cost <NUMBER>
*
* Example:
* [player, 3.3] call ace_advanced_fatigue_fnc_getMetabolicCosts
* [1, 840, 20, 1, 4] call ace_advanced_fatigue_fnc_getMetabolicCosts
*
* 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);
// Metabolic cost for walking and running is different
if (_speed > 2) then {
// 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
{
if (_x isEqualType 0) then {
_duty = _duty * _x;
} else {
_duty = _duty * (_unit call _x);
};
} forEach (values GVAR(dutyList));
if (GVAR(isSwimming)) then {
_terrainGradient = 0;
};
if (_velocity > 2) then {
(
2.10 * SIM_BODYMASS
2.1 * SIM_BODYMASS
+ 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
+ (SIM_BODYMASS + _gearMass) * (0.90 * (_velocity ^ 2) + 0.66 * _velocity * _terrainGradient)
) * 0.23 * _duty
+ _terrainFactor * (SIM_BODYMASS + _gearMass) * (0.9 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient)
) * BIOMECH_EFFICIENCY * _duty
} else {
// 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
+ 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
+ (SIM_BODYMASS + _gearMass) * (1.15 * (_velocity ^ 2) + 0.66 * _velocity * _terrainGradient)
) * 0.23 * _duty
+ 2 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
+ _terrainFactor * (SIM_BODYMASS + _gearMass) * (1.15 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient)
) * BIOMECH_EFFICIENCY * _duty
};

View File

@ -0,0 +1,38 @@
#include "..\script_component.hpp"
/*
* Author: Pterolatypus
* Calculates total weapon inertia, accounting for attachments.
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* Total inertia <NUMBER>
*
* Example:
* [ACE_player] call ace_advanced_fatigue_fnc_getWeaponInertia
*
* Public: No
*/
params [["_unit", ACE_player, [objNull]]];
private _cache = GVAR(inertiaCache);
private _weapon = currentWeapon _unit;
private _weaponAndItems = [_weapon] + (_unit weaponAccessories _weapon);
private _inertia = _cache get _weaponAndItems;
if (isNil "_inertia") then {
_inertia = 0;
private _cfgWeapons = configFile >> "CfgWeapons";
{
// if item is "" or inertia property is undefined, just ignore it
private _itemInertia = getNumber (_cfgWeapons >> _x >> "inertia");
if (isNil "_itemInertia") then { continue };
_inertia = _inertia + _itemInertia;
} forEach _weaponAndItems;
_cache set [_weaponAndItems, _inertia];
};
GVAR(inertia) = _inertia;
_inertia

View File

@ -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.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Fatigue <NUMBER>
* 2: Speed <NUMBER>
* 3: Overexhausted <BOOL>
* 2: Overexhausted <BOOL>
* 3: Forward Angle <NUMBER>
* 4: Side Angle <NUMBER>
*
* Return Value:
* None
*
* 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
*/
params ["_unit", "_fatigue", "_speed", "_overexhausted"];
#ifdef DEBUG_MODE_FULL
systemChat str _fatigue;
systemChat str vectorMagnitude velocity _unit;
#endif
params ["_unit", "_fatigue", "_overexhausted", "_fwdAngle", "_sideAngle"];
// - Audible effects ----------------------------------------------------------
GVAR(lastBreath) = GVAR(lastBreath) + 1;
if (_fatigue > 0.4 && {GVAR(lastBreath) > (_fatigue * -10 + 9)} && {!underwater _unit}) then {
if (!isGameFocused) exitWith {};
switch (true) do {
case (_fatigue < 0.6): {
playSound (QGVAR(breathLow) + str(floor random 6));
playSound (QGVAR(breathLow) + str (floor random 6));
};
case (_fatigue < 0.85): {
playSound (QGVAR(breathMid) + str(floor random 6));
playSound (QGVAR(breathMid) + str (floor random 6));
};
default {
playSound (QGVAR(breathMax) + str(floor random 6));
playSound (QGVAR(breathMax) + str (floor random 6));
};
};
GVAR(lastBreath) = 0;
};
@ -62,31 +62,35 @@ if (GVAR(isSwimming)) exitWith {
if (GVAR(setAnimExclusions) isEqualTo []) then {
_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);
} 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);
};
};
};
if ((getAnimSpeedCoef _unit) != 1) then {
if (GVAR(setAnimExclusions) isEqualTo []) then {
TRACE_1("reset",getAnimSpeedCoef _unit);
_unit setAnimSpeedCoef 1;
};
// If other components are setting setAnimSpeedCoef, do not change animSpeedCoef
if (getAnimSpeedCoef _unit != 1 && {GVAR(setAnimExclusions) isEqualTo []}) then {
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, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
} 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, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
} 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);
} 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);
};
};
@ -94,6 +98,3 @@ if (_overexhausted) then {
};
_unit setVariable [QGVAR(aimFatigue), _fatigue];
private _aimCoef = [missionNamespace, "ACE_setCustomAimCoef", "max"] call EFUNC(common,arithmeticGetResult);
_unit setCustomAimCoef _aimCoef;

View File

@ -1,7 +1,7 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Handles switching units (once on init and afterwards via Zeus).
* Author: BaerMitUmlaut, ulteq
* Handles switching units (once on init and afterwards via Zeus). Also handles CBA setting change for performance factor.
*
* Arguments:
* 0: New Unit <OBJECT>
@ -15,20 +15,24 @@
*
* Public: No
*/
params ["_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 removeEventHandler ["AnimChanged", _oldUnit getVariable [QGVAR(animHandler), -1]];
_oldUnit setVariable [QGVAR(animHandler), nil];
TRACE_1("remove old",_oldUnit getVariable QGVAR(animHandler));
_oldUnit setVariable [QGVAR(ae1Reserve), GVAR(ae1Reserve)];
_oldUnit setVariable [QGVAR(ae2Reserve), GVAR(ae2Reserve)];
_oldUnit setVariable [QGVAR(anReserve), GVAR(anReserve)];
_oldUnit setVariable [QGVAR(anFatigue), GVAR(anFatigue)];
_oldUnit setVariable [QGVAR(muscleDamage), GVAR(muscleDamage)];
_oldUnit setVariable [QGVAR(respiratoryRate), GVAR(respiratoryRate)];
};
_newUnit enableStamina false;
@ -38,6 +42,7 @@ if (_newUnit getVariable [QGVAR(animHandler), -1] == -1) then {
private _animHandler = _newUnit addEventHandler ["AnimChanged", {
GVAR(animDuty) = _this call FUNC(getAnimDuty);
}];
TRACE_1("add new",_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(anFatigue) = _newUnit getVariable [QGVAR(anFatigue), 0];
GVAR(muscleDamage) = _newUnit getVariable [QGVAR(muscleDamage), 0];
GVAR(respiratoryRate) = _newUnit getVariable [QGVAR(respiratoryRate), 0];
// Clean variables for respawning units
{
_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(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(ae1PathwayPower) = GVAR(peakPower) / (13.3 + 16.7 + 113.3) * 13.3 * ANTPERCENT ^ 1.28 * 1.362;
GVAR(ae2PathwayPower) = GVAR(peakPower) / (13.3 + 16.7 + 113.3) * 16.7 * 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) / (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(lastBreath) = 0;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Handles visual changes of the stamina bar.

View File

@ -1,6 +1,6 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Author: BaerMitUmlaut, ulteq
* Main looping function that updates fatigue values.
*
* Arguments:
@ -17,67 +17,131 @@
// Dead people don't breathe, will also handle null (map intros)
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];
_staminaBarContainer ctrlSetFade 1;
_staminaBarContainer ctrlCommit 1;
};
private _velocity = velocity ACE_player;
private _normal = surfaceNormal (getPosWorld ACE_player);
private _movementVector = vectorNormalized _velocity;
private _sideVector = vectorNormalized (_movementVector vectorCrossProduct _normal);
private _fwdAngle = asin (_movementVector select 2);
private _sideAngle = asin (_sideVector select 2);
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.
if (GVAR(isProne)) then {
_currentSpeed = _currentSpeed min 1.5;
};
if ((vehicle ACE_player == ACE_player) && {_currentSpeed > 0.1} && {isTouchingGround ACE_player || {underwater ACE_player}}) then {
_currentWork = [ACE_player, _currentSpeed] call FUNC(getMetabolicCosts);
// Get the current duty
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;
};
// 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
// Note: Muscle damage recovery is ignored as it takes multiple days
GVAR(muscleDamage) = GVAR(muscleDamage) + (_currentWork / GVAR(peakPower)) ^ 3.2 * 0.00004;
private _muscleIntegritySqrt = sqrt (1 - GVAR(muscleDamage));
GVAR(muscleDamage) = GVAR(muscleDamage) + (_currentWork / GVAR(peakPower)) ^ 3.2 * MUSCLE_TEAR_RATE;
// 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
private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * OXYGEN * _muscleIntegritySqrt;
private _ae2PathwayPowerFatigued = GVAR(ae2PathwayPower) * sqrt (GVAR(ae2Reserve) / AE2_MAXRESERVE) * OXYGEN * _muscleIntegritySqrt;
private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * _oxygen * _muscleFactor;
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
private _ae1Power = _currentWork min _ae1PathwayPowerFatigued;
private _ae2Power = ((_currentWork - _ae1Power) max 0) min _ae2PathwayPowerFatigued;
private _anPower = (_currentWork - _ae1Power - _ae2Power) max 0;
private _ae2Power = (_currentWork - _ae1Power) min _ae2PathwayPowerFatigued;
private _anPower = 0 max (_currentWork - _ae1Power - _ae2Power);
// Remove ATP from reserves for current work
GVAR(ae1Reserve) = GVAR(ae1Reserve) - _ae1Power / WATTSPERATP;
GVAR(ae2Reserve) = GVAR(ae2Reserve) - _ae2Power / WATTSPERATP;
GVAR(anReserve) = GVAR(anReserve) - _anPower / WATTSPERATP;
// Increase anearobic fatigue
GVAR(anFatigue) = GVAR(anFatigue) + _anPower * (0.057 / GVAR(peakPower)) * 1.1;
GVAR(ae1Reserve) = 0 max (GVAR(ae1Reserve) - _ae1Power / GVAR(aeWattsPerATP));
GVAR(ae2Reserve) = 0 max (GVAR(ae2Reserve) - _ae2Power / GVAR(aeWattsPerATP));
GVAR(anReserve) = 0 max (GVAR(anReserve) - _anPower / GVAR(anWattsPerATP));
// Acidosis accumulation
GVAR(anFatigue) = GVAR(anFatigue) + _anPower * GVAR(maxPowerFatigueRatio) * 1.1;
// Aerobic ATP reserve recovery
GVAR(ae1Reserve) = ((GVAR(ae1Reserve) + OXYGEN * 6.60 * (GVAR(ae1PathwayPower) - _ae1Power) / GVAR(ae1PathwayPower) * GVAR(recoveryFactor)) min AE1_MAXRESERVE) max 0;
GVAR(ae2Reserve) = ((GVAR(ae2Reserve) + OXYGEN * 5.83 * (GVAR(ae2PathwayPower) - _ae2Power) / GVAR(ae2PathwayPower) * GVAR(recoveryFactor)) min AE2_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 * GVAR(recoveryFactor) * AE2_ATP_RECOVERY * (GVAR(ae2PathwayPower) - _ae2Power) / GVAR(ae2PathwayPower)) min AE2_MAXRESERVE;
// Anaerobic ATP reserver and fatigue recovery
GVAR(anReserve) = ((GVAR(anReserve)
+ (_ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power) / GVAR(VO2MaxPower) * 56.7 * GVAR(anFatigue) ^ 2 * GVAR(recoveryFactor)
) min AN_MAXRESERVE) max 0;
private _aeSurplus = _ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power;
GVAR(anFatigue) = ((GVAR(anFatigue)
- (_ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power) * (0.057 / GVAR(peakPower)) * GVAR(anFatigue) ^ 2 * GVAR(recoveryFactor)
) min 1) max 0;
// Anaerobic ATP reserve recovery
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
// Acidosis recovery
GVAR(anFatigue) = 0 max (GVAR(anFatigue) - _aeSurplus * GVAR(maxPowerFatigueRatio) * GVAR(recoveryFactor) * GVAR(anFatigue) ^ 2) min 1;
private _aeReservePercentage = (GVAR(ae1Reserve) / AE1_MAXRESERVE + GVAR(ae2Reserve) / AE2_MAXRESERVE) / 2;
private _anReservePercentage = GVAR(anReserve) / AN_MAXRESERVE;
private _perceivedFatigue = 1 - (_anReservePercentage min _aeReservePercentage);
// Respiratory rate decrease
GVAR(respiratoryRate) = GVAR(respiratoryRate) * GVAR(respiratoryBufferDivisor);
[ACE_player, _perceivedFatigue, _currentSpeed, GVAR(anReserve) == 0] call FUNC(handleEffects);
// 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(anReservePercentage) = GVAR(anReserve) / AN_MAXRESERVE;
private _perceivedFatigue = 1 - (GVAR(anReservePercentage) min GVAR(aeReservePercentage));
#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
[ACE_player, _perceivedFatigue, GVAR(anReserve) == 0, _fwdAngle, _sideAngle] call FUNC(handleEffects);
if (GVAR(enableStaminaBar)) then {
[GVAR(anReserve) / AN_MAXRESERVE] call FUNC(handleStaminaBar);
};
[FUNC(mainLoop), [], 1] call CBA_fnc_waitAndExecute;
[LINKFUNC(mainLoop), [], 1] call CBA_fnc_waitAndExecute;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Initializes the module settings.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Removes a duty factor.

View 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]];
}];

View File

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

View File

@ -0,0 +1,92 @@
[
QGVAR(enabled),
"CHECKBOX",
[LSTRING(Enabled), LSTRING(Enabled_Description)],
LSTRING(DisplayName),
true,
1,
{
if (!_this) then {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlSetFade 1;
_staminaBarContainer ctrlCommit 0;
};
[QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)
},
true // Needs mission restart
] call CBA_fnc_addSetting;
[
QGVAR(enableStaminaBar),
"CHECKBOX",
[LSTRING(EnableStaminaBar), LSTRING(EnableStaminaBar_Description)],
LSTRING(DisplayName),
true,
1,
{
if (!_this) then {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlSetFade 1;
_staminaBarContainer ctrlCommit 0;
};
}
] call CBA_fnc_addSetting;
[
QGVAR(fadeStaminaBar),
"CHECKBOX",
[LSTRING(FadeStaminaBar), LSTRING(FadeStaminaBar_Description)],
LSTRING(DisplayName),
true,
0,
{
if (!_this && GVAR(enabled) && GVAR(enableStaminaBar)) then {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlSetFade 0;
_staminaBarContainer ctrlCommit 0;
};
}
] call CBA_fnc_addSetting;
[
QGVAR(performanceFactor),
"SLIDER",
[LSTRING(PerformanceFactor), LSTRING(PerformanceFactor_Description)],
LSTRING(DisplayName),
[0, 10, 1, 2],
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;
[
QGVAR(recoveryFactor),
"SLIDER",
[LSTRING(RecoveryFactor), LSTRING(RecoveryFactor_Description)],
LSTRING(DisplayName),
[0, 10, 1, 2],
1
] call CBA_fnc_addSetting;
[
QGVAR(loadFactor),
"SLIDER",
[LSTRING(LoadFactor), LSTRING(LoadFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 2],
1
] call CBA_fnc_addSetting;
[
QGVAR(terrainGradientFactor),
"SLIDER",
[LSTRING(TerrainGradientFactor), LSTRING(TerrainGradientFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 2],
1
] call CBA_fnc_addSetting;

View File

@ -1,91 +0,0 @@
[
QGVAR(enabled),
"CHECKBOX",
[LSTRING(Enabled), LSTRING(Enabled_Description)],
LSTRING(DisplayName),
true,
true, {
if (!_this) then {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlSetFade 1;
_staminaBarContainer ctrlCommit 0;
};
[QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)
},
true // Needs mission restart
] call CBA_fnc_addSetting;
[
QGVAR(enableStaminaBar),
"CHECKBOX",
[LSTRING(EnableStaminaBar), LSTRING(EnableStaminaBar_Description)],
LSTRING(DisplayName),
true,
true, {
if (!_this) then {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlSetFade 1;
_staminaBarContainer ctrlCommit 0;
};
}
] call CBA_fnc_addSetting;
[
QGVAR(fadeStaminaBar),
"CHECKBOX",
[LSTRING(FadeStaminaBar), LSTRING(FadeStaminaBar_Description)],
LSTRING(DisplayName),
true,
false, {
if (!_this && GVAR(enabled) && GVAR(enableStaminaBar)) then {
private _staminaBarContainer = uiNamespace getVariable [QGVAR(staminaBarContainer), controlNull];
_staminaBarContainer ctrlSetFade 0;
_staminaBarContainer ctrlCommit 0;
};
}
] call CBA_fnc_addSetting;
[
QGVAR(performanceFactor),
"SLIDER",
[LSTRING(PerformanceFactor), LSTRING(PerformanceFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 1],
true
] call CBA_fnc_addSetting;
[
QGVAR(recoveryFactor),
"SLIDER",
[LSTRING(RecoveryFactor), LSTRING(RecoveryFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 1],
true
] call CBA_fnc_addSetting;
[
QGVAR(loadFactor),
"SLIDER",
[LSTRING(LoadFactor), LSTRING(LoadFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 1],
true
] call CBA_fnc_addSetting;
[
QGVAR(terrainGradientFactor),
"SLIDER",
[LSTRING(TerrainGradientFactor), LSTRING(TerrainGradientFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 1],
true
] call CBA_fnc_addSetting;
[
QGVAR(swayFactor),
"SLIDER",
[LSTRING(SwayFactor), LSTRING(SwayFactor_Description)],
LSTRING(DisplayName),
[0, 5, 1, 1],
true
] call CBA_fnc_addSetting;

View File

@ -16,14 +16,28 @@
#include "\z\ace\addons\main\script_macros.hpp"
#define UNDERWEAR_WEIGHT 3.5
#define ANTPERCENT 0.8
#define SIM_BODYMASS 70
#define JOULES_PER_ML_O2 20.9
#define VO2MAX_STRENGTH 4.1
#define REE 18.83 //((0.5617 * SIM_BODYMASS + 42.57) * 0.23)
#define OXYGEN 0.9
#define WATTSPERATP 7
#define BIOMECH_EFFICIENCY 0.23
#define REE 18.83 // ((0.5617 * SIM_BODYMASS + 42.57) * BIOMECH_EFFICIENCY)
#define AE1_MAXRESERVE 4000000
#define AE2_MAXRESERVE 84000
#define AN_MAXRESERVE 2300
#define RESPIRATORY_BUFFER 60
#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

View File

@ -7,7 +7,7 @@
<German>ACE Erweiterte Ausdauer</German>
<Chinese>ACE 進階疲勞</Chinese>
<Chinesesimp>ACE 进阶体力</Chinesesimp>
<Japanese>ACE アドバンスド ファティーグ</Japanese>
<Japanese>ACE アドバンスド疲労</Japanese>
<Italian>ACE Fatica Avanzata</Italian>
<Korean>ACE 고급 피로도</Korean>
<French>ACE Fatigue avancée</French>
@ -41,10 +41,10 @@
<Polish>Wpływa na ogólną wydolność organizmu u wszystkich graczy bez ustawionego niestandardowego współczynnika. Więcej znaczy lepiej.</Polish>
<Korean>모든 성능이 임의로 설정된 값 없이 영향받습니다. 값이 클수록 더 나은 성능을 발휘합니다</Korean>
<French>Impacte la performance globale de tous les joueurs n'ayant pas de facteur personnalisé.\nPlus la valeur est élevée, plus le joueur est performant.</French>
<Italian>Influenza qualsiasi prestazione di tutti i giocatori smuniti di un fattore personalizzato. Maggiore significa migliore.</Italian>
<Italian>Influenza la prestazione generale di tutti i giocatori smuniti di un fattore personalizzato. Maggiore significa migliore.</Italian>
<Chinese>影響所有玩家的體力表現,值越高代表體力越好</Chinese>
<Chinesesimp>影响所有玩家的体力表现,值越高代表体力越好</Chinesesimp>
<Russian>Влияет на общую производительность игроков, у которых не задано персональное значение.</Russian>
<Russian>Влияет на общую производительность игроков, у которых не задано персональное значение. Чем выше, тем лучше.</Russian>
<Portuguese>Influencia na performance geral de todos os jogadores sem nenhum fator personalizado. Quanto maior, melhor.</Portuguese>
<Czech>Ovlivňuje celkový výkon všech hráčů bez vlastního faktoru. Vyšší znamená lépe.</Czech>
</Key>
@ -56,10 +56,10 @@
<Polish>Wpływa na ogólną wydolność tej jednostki. Więcej znaczy lepiej.</Polish>
<Korean>모든 성능이 이 단위로 영향을 받습니다. 값이 클수록 더 나은 성능을 발휘합니다</Korean>
<French>Impacte la performance globale de cette unité.\nPlus la valeur est élevée, plus l'unité est performante.</French>
<Italian>Influenza qualsiasi prestazione di questa unità. Maggiore significa migliore.</Italian>
<Italian>Influenza la prestazione personalizzata di questa unità. Maggiore significa migliore.</Italian>
<Chinese>影響這個單位的體力表現,值越高代表體力越好</Chinese>
<Chinesesimp>影响这个单位的体力表现,值越高代表体力越好</Chinesesimp>
<Russian>Влияет на общую производительность юнита.</Russian>
<Russian>Влияет на общую производительность юнита.Чем выше, тем лучше.</Russian>
<Portuguese>Influencia na performance geral dessa unidade. Quanto maior, melhor.</Portuguese>
<Czech>Ovlivňuje celkový výkon této jednotky. Vyšší znamená lépe.</Czech>
</Key>
@ -87,7 +87,7 @@
<Polish>Wpływa na czas regeneracji podczas postoju. Więcej znaczy szybciej.</Polish>
<Korean>얼마나 빨리 회복하는지를 바꿉니다. 값이 클수록 더 나은 성능을 발휘합니다</Korean>
<French>Modifie la vitesse à laquelle le joueur récupère lorsqu'il se repose.\nPlus la valeur est élevée, plus la récupération est rapide.</French>
<Italian>Determina in quanto tempo il giocatore recupera quando rilassato. Maggiore significa migliore.</Italian>
<Italian>Determina quanto velocemente il giocatore recupera le energie quando si ferma. Maggiore significa migliore.</Italian>
<Chinese>決定玩家休息多久就能回復體力,值越高恢復越快</Chinese>
<Chinesesimp>决定玩家休息多久就能恢复体力,值越高恢复越快</Chinesesimp>
<Russian>Изменяет скорость восстановления игрока во время отдыха. Чем выше, тем быстрее.</Russian>
@ -102,7 +102,7 @@
<Polish>Współczynnik masy ekwipunku</Polish>
<Korean>부담 요인</Korean>
<French>Facteur de charge</French>
<Italian>Fattore Caricamento</Italian>
<Italian>Fattore Carico</Italian>
<Chinese>負重量</Chinese>
<Chinesesimp>重量系数</Chinesesimp>
<Russian>Фактор нагрузки</Russian>
@ -117,7 +117,7 @@
<Polish>Zmniejsza lub zwiększa wpływ ciężaru ekwipunku na wydolność gracza. Zero oznacza kompletny brak wpływu na wydolność.</Polish>
<Korean>플레이어가 무게에 따라 얼마나 영향받는지를 증가시키거나 감소시킵니다. 0의 경우 플레이어가 장비 무게에 영향받지 않습니다.</Korean>
<French>Augmente ou diminue l'influence du poids sur les performances du joueur.\nUne valeur nulle indique que le poids de l'équipement n'a aucun impact sur les performances.</French>
<Italian>Incrementa o decrementa quanto il peso influenza le prestazioni dei giocatori. Zero significa che il peso dell'equipaggiamento non ha alcuna influenza nelle prestazioni.</Italian>
<Italian>Determina quanto il peso trasportato influenza le prestazioni dei giocatori. Zero significa che il peso dell'equipaggiamento non influisce sulle prestazioni.</Italian>
<Chinese>增加或降低玩家所能承受的負重量. 如設定值為0, 代表裝備的重量將不會影響到玩家的體力表現</Chinese>
<Chinesesimp>增加或降低玩家所能承受的负重量。如设定值为0代表装备的重量将不会影响到玩家的体力表现</Chinesesimp>
<Russian>Увеличивает или уменьшает вес, влияющий на производительность игроков. Ноль означает, что вес снаряжения не влияет на производительность</Russian>
@ -147,52 +147,22 @@
<Polish>Wpływa na to w jakim stopniu stromy teren wpływa na utratę wytrzymałości. Więcej oznacza szybszą utratę wytrzymałości.</Polish>
<Korean>경사도에 따라 얼마나 피로해지는지를 정합니다. 값이 클수록 더 많은 피로를 유발합니다.</Korean>
<French>Définit à quel point un terrain escarpé réduit l'endurance du joueur.\nPlus la valeur est élevée, moins le joueur est endurant.</French>
<Italian>Stabilisce quanto la pendenza del terreno incrementa la perdita della stamina. Maggiore significa più stamina persa.</Italian>
<Italian>Determina quanto la pendenza del terreno incrementa la perdita della stamina. Maggiore significa più stamina persa.</Italian>
<Chinese>設定陡峭的地形將會影響多少體力的流失,值越高代表體力流失越快</Chinese>
<Chinesesimp>设定陡峭的地形将会影响多少体力的流失速度,值越高代表体力流失越快</Chinesesimp>
<Russian>Устанавливает, насколько крутая местность увеличивает потерю выносливости. Чем выше, тем быстрее теряется выносливость.</Russian>
<Portuguese>Define o quanto que um terreno íngrime aumenta na perda de estamina. Quanto maior, maior a perda de estamina.</Portuguese>
<Czech>Nastavuje, o kolik strmý terén zvyšuje ztrátu výdrže. Vyšší znamená vyšší ztrátu výdrže.</Czech>
</Key>
<Key ID="STR_ACE_Advanced_Fatigue_SwayFactor">
<English>Sway factor</English>
<Spanish>Factor de balanceo de mira</Spanish>
<German>Verwacklungsfaktor</German>
<Japanese>手ぶれ因数</Japanese>
<Chinesesimp>抖动系数</Chinesesimp>
<Chinese>抖動因素</Chinese>
<French>Facteur de tremblement</French>
<Italian>Fattore di oscillazione</Italian>
<Polish>Czynnik kołysania</Polish>
<Russian>Фактор колебания прицела</Russian>
<Portuguese>Fator de Balanço de Mira</Portuguese>
<Czech>Faktor kývání</Czech>
<Korean>손떨림 정도</Korean>
</Key>
<Key ID="STR_ACE_Advanced_Fatigue_SwayFactor_Description">
<English>Influences the amount of weapon sway. Higher means more sway.</English>
<Spanish>Afecta al la estabilidad de la mira. Más alto significa más balanceo</Spanish>
<German>Beeinflusst den Faktor, wie ruhig man eine Waffe halten kann. Ein höherer Wert bedeutet weniger Stabilisierung</German>
<Japanese>武器を持つ手のぶれ度合いを設定します。 値が高ければ高いほど、手ぶれが強くなります。</Japanese>
<Chinesesimp>影响手持武器的晃动程度,数值越高,抖动的越厉害。</Chinesesimp>
<Chinese>影響手持武器晃動程度,數值越高抖動越厲害</Chinese>
<French>Influe sur l'amplitude du tremblement de l'arme. Une valeur plus élevée signifie plus de tremblement.</French>
<Italian>Influenza l'ammontare di oscillazione dell'arma. Maggiore significa più oscillazione.</Italian>
<Polish>Wpływa na poziom kołysania broni. Większa ilość znaczy większe kołysanie.</Polish>
<Russian>Влияет на колебания прицела оружия. Чем выше - тем больше.</Russian>
<Portuguese>Influencia a quantidade de balanço da mira da arma. Quanto maior, mais balanço.</Portuguese>
<Czech>Ovlivňuje množství kývání zbraní. Vyšší znamená více kývání.</Czech>
<Korean>손떨림의 정도를 정합니다. 높을 수록 많이 휘적입니다.</Korean>
</Key>
<Key ID="STR_ACE_Advanced_Fatigue_Enabled">
<English>Enabled</English>
<Spanish>Activada</Spanish>
<German>Aktiv</German>
<Japanese>アドバンスド ファティーグを有効化</Japanese>
<Japanese>有効化</Japanese>
<Polish>Włączone</Polish>
<Korean>활성화</Korean>
<French>Activé</French>
<Italian>Abilitato</Italian>
<Italian>Abilitata</Italian>
<Chinese>啟用</Chinese>
<Chinesesimp>启用</Chinesesimp>
<Russian>Включена</Russian>
@ -203,14 +173,14 @@
<English>Enables/disables Advanced Fatigue.</English>
<Spanish>Activa/desactiva la fatiga avanzada</Spanish>
<German>Aktiviert/deaktiviert Advanced Fatigue.</German>
<Japanese>アドバンスド ファティーグを有効化します。</Japanese>
<Japanese>アドバンスド疲労は高度な疲労管理システムを有効化します。</Japanese>
<Polish>Włącza/wyłącza zaawansowaną wytrzymałość</Polish>
<Korean>고급 피로도 활성화/비활성화</Korean>
<French>Active/Désactive la fatigue avancée.</French>
<Italian>Abilita/disabilita la Fatica Avanzata.</Italian>
<Italian>Abilita/Disabilita la Fatica Avanzata.</Italian>
<Chinese>啟用/關閉進階體力.</Chinese>
<Chinesesimp>启用/关闭进阶体力。</Chinesesimp>
<Russian>Включает / Отключает Продвинутую усталость</Russian>
<Russian>Включает/отключает Продвинутую усталость</Russian>
<Portuguese>Ativa/Desativa Fadiga Avançada.</Portuguese>
<Czech>Aktivuje / deaktivuje Pokročilou únavu.</Czech>
</Key>
@ -251,7 +221,7 @@
<German>Blende Ausdauerleiste automatisch aus</German>
<Chinese>體力條自動淡去</Chinese>
<Chinesesimp>自动淡化体力条</Chinesesimp>
<Italian>Dissolvenza automatica della barra della stamina</Italian>
<Italian>Nascondi in automatico la barra della stamina</Italian>
<Czech>Automaticky schovat lištu výdrže</Czech>
<French>Fondu automatique de la barre d'endurance</French>
<Japanese>自動的にスタミナバーを非表示</Japanese>

View File

@ -1,26 +1,19 @@
#include "script_component.hpp"
// Fired XEH
[QGVAR(throwFiredXEH), FUNC(throwFiredXEH)] call CBA_fnc_addEventHandler;
GVAR(ammoEventHandlers) = createHashMap;
[QGVAR(throwFiredXEH), LINKFUNC(throwFiredXEH)] call CBA_fnc_addEventHandler;
// Exit on HC
if (!hasInterface) exitWith {};
// 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]; };
} count (getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines"));
nil
} count getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles");
// Temporary Wind Info indication
GVAR(tempWindInfo) = false;
// Add keybinds
["ACE3 Weapons", QGVAR(prepare), localize LSTRING(Prepare), {
// Condition
if (!([ACE_player] call FUNC(canPrepare))) exitWith {false};
if !([ACE_player] call FUNC(canPrepare)) exitWith {false};
if (EGVAR(common,isReloading)) exitWith {true};
// Statement

View File

@ -6,6 +6,6 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
#include "initSettings.sqf"
#include "initSettings.inc.sqf"
ADDON = true;

View File

@ -1,3 +1,21 @@
#include "script_component.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];

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Jonpas
* Checks if a throwable can be prepared.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Jonpas
* Checks if a throwable can be thrown.
@ -19,7 +19,7 @@ params ["_unit"];
if !(_unit getVariable [QGVAR(inHand), false]) exitWith {false};
if (vehicle _unit != _unit) exitWith {
if (!isNull objectParent _unit) exitWith {
private _startPos = eyePos _unit;
private _aimLinePos = AGLToASL (positionCameraToWorld [0, 0, 1]);
private _intersections = lineIntersectsSurfaces [_startPos, _aimLinePos, _unit, objNull, false];

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Zapat, Dslyecxi, Jonpas
* Draws throw arc.

View File

@ -1,6 +1,6 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas, SilentSpike
* Author: Dslyecxi, Jonpas, kymckay
* Handles drawing the currently selected or cooked throwable.
*
* Arguments:
@ -43,13 +43,10 @@ if ((!_primed) && {!((_throwableMag in (uniformItems ACE_player)) || {_throwable
// Get correct throw power for primed grenade
if (_primed) then {
private _ammoType = typeOf _activeThrowable;
_throwableMag = GVAR(ammoMagLookup) getVariable _ammoType;
if (isNil "_throwableMag") then {
// What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke)
// Just use HandGrenade as it has an average initSpeed value
_throwableMag = "HandGrenade";
};
// If ammo type is not found:
// What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke)
// Just use HandGrenade as it has an average initSpeed value
_throwableMag = (uiNamespace getVariable QGVAR(ammoMagLookup)) getOrDefault [typeOf _activeThrowable, "HandGrenade"];
};
// Some throwables have different classname for magazine and ammo

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Exits throw mode.
@ -53,6 +53,12 @@ _unit setVariable [QGVAR(dropDistance), DROP_DISTANCE_DEFAULT];
// Remove controls hint (check if ever enabled is inside the function)
call EFUNC(interaction,hideMouseHint);
// Hide wind info after throw, if it was temporarily enabled for the throw
if (GVAR(tempWindInfo)) then {
EGVAR(weather,WindInfo) = false;
GVAR(tempWindInfo) = false;
};
// Remove throw action
[_unit, "DefaultAction", _unit getVariable [QGVAR(throwAction), -1]] call EFUNC(common,removeActionEventHandler);

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Retrieve muzzle name from config.
@ -17,9 +17,9 @@
params ["_magazineClassname"];
_magazineClassname = toLower _magazineClassname;
_magazineClassname = toLowerANSI _magazineClassname;
private _throwMuzzles = getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles");
_throwMuzzles = _throwMuzzles select {_magazineClassname in ((getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines")) apply {toLower _x})};
_throwMuzzles = _throwMuzzles select {_magazineClassname in ((getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines")) apply {toLowerANSI _x})};
[_throwMuzzles select 0, ""] select (_throwMuzzles isEqualTo [])

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Jonpas
* Initializes the Advanced Throwing module.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Key down event.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Mouse button down event.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Mouse scroll wheel changed event.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Jonpas
* Picks up a throwable from the ground.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Prepares throwable or selects the next.
@ -21,7 +21,7 @@ TRACE_1("params",_unit);
// Select next throwable if one already in hand
if (_unit getVariable [QGVAR(inHand), false]) exitWith {
TRACE_1("inHand",_unit);
if (!(_unit getVariable [QGVAR(primed), false])) then {
if !(_unit getVariable [QGVAR(primed), false]) then {
TRACE_1("not primed",_unit);
// 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)
@ -35,6 +35,11 @@ if (isNull (_unit getVariable [QGVAR(activeThrowable), objNull]) && {(currentThr
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];

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Primes the throwable, creates global throwable vehicle and throws Fired XEH.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: PabstMirror, Jonpas
* When interact_menu starts rendering (from "interact_keyDown" event).
@ -44,8 +44,7 @@
_addedPickUpHelpers pushBack _pickUpHelper;
_throwablesHelped pushBack _x;
};
nil
} count _nearThrowables;
} forEach _nearThrowables;
_args set [0, getPosASL ACE_player];
_args set [3, _nearThrowables];
@ -56,11 +55,10 @@
{
// Only handling with attachTo works nicely
_x attachTo [_x getVariable [QGVAR(throwable), objNull], [0, 0, 0]];
nil
} count _addedPickUpHelpers;
} forEach _addedPickUpHelpers;
} else {
TRACE_1("Cleaning Pick Up Helpers",count _addedPickUpHelpers);
{deleteVehicle _x} count _addedPickUpHelpers;
{deleteVehicle _x} forEach _addedPickUpHelpers;
[_idPFH] call CBA_fnc_removePerFrameHandler;
};
}, 0, [(getPosASL ACE_player) vectorAdd [-100, 0, 0], [], [], []]] call CBA_fnc_addPerFrameHandler;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dslyecxi, Jonpas
* Throw selected throwable.
@ -20,7 +20,7 @@ TRACE_1("params",_unit);
// 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
if (!(_unit getVariable [QGVAR(primed), false])) then {
if !(_unit getVariable [QGVAR(primed), false]) then {
[_unit] call FUNC(prime);
};
@ -45,7 +45,7 @@ if (!(_unit getVariable [QGVAR(primed), false])) then {
private _newVelocity = (_p1 vectorFromTo _p2) vectorMultiply _velocity;
// Adjust for throwing from inside vehicles, where we have a vehicle-based velocity that can't be compensated for by a human
if (vehicle _unit != _unit) then {
if (!isNull objectParent _unit) then {
_newVelocity = _newVelocity vectorAdd (velocity (vehicle _unit));
};

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: CBA Team
* Throws Fired XEH.
@ -20,14 +20,25 @@
*
* Public: No
*/
params ["_unit", "", "_muzzle", "", "_ammo"];
TRACE_1("Fired",_this);
{
_this call _x;
} forEach ((_this select 0) getVariable "cba_xeh_fired");
} forEach (_unit getVariable "cba_xeh_fired");
// Call muzzle fired EH
{
_this call compile getText (_x >> "fired");
} forEach (configProperties [configFile >> "CfgWeapons" >> "Throw" >> (_this select 2) >> "EventHandlers", "isClass _x", true]);
} forEach (configProperties [configFile >> "CfgWeapons" >> "Throw" >> _muzzle >> "EventHandlers", "isClass _x", true]);
// Call ammo fired EH
{ _this call _x } forEach (GVAR(ammoEventHandlers) getOrDefaultCall [_ammo, {
private _cfg = configFile >> "CfgAmmo" >> _ammo >> "EventHandlers";
private _eventHandlers = [];
{
private _eh = getText (_x >> "fired");
if (_eh != "") then { _eventHandlers pushBack compile _eh };
} forEach ([_cfg] + configProperties [_cfg, "isClass _x", true]);
_eventHandlers
}, true]);

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Jonpas
* Updates controls hints based on current state.

View File

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

View File

@ -0,0 +1,50 @@
private _category = format ["ACE %1", localize LSTRING(Category)];
[
QGVAR(enabled),
"CHECKBOX",
[LSTRING(Enable_DisplayName), LSTRING(Enable_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;
[
QGVAR(showThrowArc),
"CHECKBOX",
[LSTRING(ShowThrowArc_DisplayName), LSTRING(ShowThrowArc_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;
[
QGVAR(showMouseControls), "CHECKBOX",
[LSTRING(ShowMouseControls_DisplayName), LSTRING(ShowMouseControls_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;
[
QGVAR(enablePickUp), "CHECKBOX",
[LSTRING(EnablePickUp_DisplayName), LSTRING(EnablePickUp_Description)],
_category,
true,
1
] call CBA_fnc_addSetting;
[
QGVAR(enablePickUpAttached), "CHECKBOX",
[LSTRING(EnablePickUpAttached_DisplayName), LSTRING(EnablePickUpAttached_Description)],
_category,
true,
1
] call CBA_fnc_addSetting;
[
QGVAR(enableTempWindInfo), "CHECKBOX",
[LSTRING(EnableTempWindInfo_DisplayName), LSTRING(EnableTempWindInfo_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;

View File

@ -1,42 +0,0 @@
private _category = format ["ACE %1", localize LSTRING(Category)];
[
QGVAR(enabled),
"CHECKBOX",
[LSTRING(Enable_DisplayName), LSTRING(Enable_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;
[
QGVAR(showThrowArc),
"CHECKBOX",
[LSTRING(ShowThrowArc_DisplayName), LSTRING(ShowThrowArc_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;
[
QGVAR(showMouseControls), "CHECKBOX",
[LSTRING(ShowMouseControls_DisplayName), LSTRING(ShowMouseControls_Description)],
_category,
true,
0
] call CBA_fnc_addSetting;
[
QGVAR(enablePickUp), "CHECKBOX",
[LSTRING(EnablePickUp_DisplayName), LSTRING(EnablePickUp_Description)],
_category,
true,
1
] call CBA_fnc_addSetting;
[
QGVAR(enablePickUpAttached), "CHECKBOX",
[LSTRING(EnablePickUpAttached_DisplayName), LSTRING(EnablePickUpAttached_Description)],
_category,
true,
1
] call CBA_fnc_addSetting;

View File

@ -5,7 +5,7 @@
<English>Advanced Throwing</English>
<Spanish>Lanzamiento Avanzado</Spanish>
<Russian>Улучшенный бросок гранат</Russian>
<Japanese>アドバンスド スローイング</Japanese>
<Japanese>アドバンスド投擲</Japanese>
<Polish>Zaawansowane rzucanie</Polish>
<German>Erweitertes Wurfsystem</German>
<Korean>고급 투척</Korean>
@ -21,7 +21,7 @@
<English>Allows changing advanced throwing behaviour.</English>
<Spanish>Permite modificar el comportamiento del lanzamiento avanzado</Spanish>
<Russian>Позволяет настраивать поведение улучшенного броска гранат.</Russian>
<Japanese>アドバンスド スローイングの動作挙動を変更します。</Japanese>
<Japanese>アドバンスド投擲は投擲の高度な動作挙動を変更可能にします。</Japanese>
<Polish>Zezwala na zmianę zachowania zaawansowanego trybu rzucania.</Polish>
<German>Erlaubt es, das Verhalten des erweiterten Wurfsystems zu ändern.</German>
<Korean>고급 투척 행위를 허가합니다</Korean>
@ -36,7 +36,7 @@
<English>Enable Advanced Throwing</English>
<Spanish>Activar Lanzamiento Avanzado</Spanish>
<Russian>Вкл. улучшенный бросок</Russian>
<Japanese>アドバンスド スローイングを有効化</Japanese>
<Japanese>アドバンスド投擲を有効化</Japanese>
<Polish>Aktywuj zaawansowane rzucanie</Polish>
<German>Aktiviere erweitertes Wurfsystem</German>
<Korean>고급 투척 활성화 </Korean>
@ -52,7 +52,7 @@
<English>Enables advanced throwing system.</English>
<Spanish>Activa el Lanzamiento Avanzado</Spanish>
<Russian>Включает систему улучшенного броска.</Russian>
<Japanese>アドバンスド スローイングを有効化します。</Japanese>
<Japanese>アドバンスド投擲は高度な投擲システムを有効化します。</Japanese>
<Polish>Aktywuje system zaawansowanego rzucania.</Polish>
<German>Aktiviert das erweiterte Wurfsystem.</German>
<Korean>고급 투척을 활성화 합니다</Korean>
@ -68,7 +68,7 @@
<English>Show Throw Arc</English>
<Spanish>Mostrar Arco de Lanzamiento</Spanish>
<Russian>Показать траекторию броска</Russian>
<Japanese>てき軌道を表示</Japanese>
<Japanese>軌道を表示</Japanese>
<Polish>Pokaż trasę lotu</Polish>
<German>Zeige Wurfbogen</German>
<Korean>투척 궤적 표시</Korean>
@ -84,7 +84,7 @@
<English>Enables visualization of the throw arc (where throwable will fly).</English>
<Spanish>Activa la visualización del arco de lanzamiento (donde irá el objeto lanzado)</Spanish>
<Russian>Включает визуализацию траектории броска (как полетит граната).</Russian>
<Japanese>てき軌道 (投てき物がどこに飛ぶか) の表示を有効化します。</Japanese>
<Japanese>擲軌道 (投擲物がどこに飛ぶか) の表示を有効化します。</Japanese>
<Polish>Wyświetla wizualizację trasy przelotu granatu.</Polish>
<German>Aktiviert die Visualisierung des Wurfbogens (wohin das Objekt geworfen werden wird).</German>
<Korean>투척 궤도를 시각화 합니다(투척물이 어디로 갈지)</Korean>
@ -99,12 +99,12 @@
<English>Show Throwing Mouse Controls</English>
<Spanish>Mostrar controles de ratón de lanzamiento</Spanish>
<Russian>Показывать управление мышью</Russian>
<Japanese>てきのマウス操作を表示</Japanese>
<Japanese>のマウス操作を表示</Japanese>
<Polish>Pokaż podpowiedzi sterowania myszą</Polish>
<German>Zeige Maussteuerung beim Werfen</German>
<Korean>마우스 조작 표시</Korean>
<French>Afficher les contrôles à la souris du lancé</French>
<Italian>Mostra Comandi Mouse Lancio</Italian>
<Italian>Mostra Comandi Mouse di Lancio</Italian>
<Chinese>顯示滑鼠投擲控制提示</Chinese>
<Chinesesimp>显示鼠标投掷控制提示</Chinesesimp>
<Portuguese>Mostrar os controles de mouse para Arremesso</Portuguese>
@ -114,7 +114,7 @@
<English>Enables visual cues for mouse controls when throwable is prepared.</English>
<Spanish>Activa muestras visuales para los controles del ratón cuando el objeto lanzable está preparado</Spanish>
<Russian>Включает отображение подсказок по управлению мышью, когда граната подготовлена.</Russian>
<Japanese>てき物を構える時、マウス操作の説明表示を有効化します。</Japanese>
<Japanese>物を構える時、マウス操作の説明表示を有効化します。</Japanese>
<Polish>Wyświetla podpowiedzi sterowania myszą kiedy obiekt miotany jest w ręku.</Polish>
<German>Aktiviert visuelle Hinweise zur Maussteuerung, wenn ein Objekt zum Werfen vorbereitet wird.</German>
<Korean>투척물을 준비시 마우스 조작을 시각화해서 보여줍니다</Korean>
@ -129,12 +129,12 @@
<English>Enable Throwables Pick Up</English>
<Spanish>Habilitar recoger objetos lanzados</Spanish>
<Russian>Вкл. подбор гранат</Russian>
<Japanese>てき物の拾い上げを有効化</Japanese>
<Japanese>物の拾い上げを有効化</Japanese>
<Polish>Zezwól na podnoszenie obiektów miotanych</Polish>
<German>Aktiviere Aufheben von Wurfobjekten</German>
<Korean>투척물 줍기 활성화</Korean>
<French>Permettre le ramassage d'objets lançables</French>
<Italian>Abilita Raccogli Oggetti</Italian>
<Italian>Abilita Raccolta Lanciabili</Italian>
<Chinese>啟用可撿取地面投擲物</Chinese>
<Chinesesimp>启用捡取地面投掷物</Chinesesimp>
<Portuguese>Permitir pegar arremessáveis</Portuguese>
@ -144,12 +144,12 @@
<English>Enables ability to pick up throwables from the ground.</English>
<Spanish>Activa la habilidad de coger objetos lanzados del suelo</Spanish>
<Russian>Включает возможность подбирать гранаты с земли.</Russian>
<Japanese>地面に落ちている投てき物を拾い上げる機能を有効化します。</Japanese>
<Japanese>地面に落ちている投擲物を拾う機能を有効化します。</Japanese>
<Polish>Umożliwia podnoszenie obiektów miotanych z ziemi.</Polish>
<German>Aktiviert die Möglichkeit, geworfene Objekte wieder vom Boden aufzuheben.</German>
<Korean>땅에 떨어진 투척물을 주울 수 있게 해줍니다.</Korean>
<French>Active la possibilité de ramasser des objets lançables du sol.</French>
<Italian>Abilita la possibilità di raccogliere un oggetto lanciabile da terra.</Italian>
<Italian>Permette ai giocatori di raccogliere un oggetto lanciabile da terra.</Italian>
<Chinese>啟用後, 可撿取地面上的投擲物</Chinese>
<Chinesesimp>启用后,可捡取地面上的投掷物</Chinesesimp>
<Portuguese>Permite que objetos arremessados sejam pegos do chão. (ACE Menu de Interação)</Portuguese>
@ -159,12 +159,12 @@
<English>Enable Attached Throwables Pick Up</English>
<Spanish>Activar coger objetos lanzables que se enganchan</Spanish>
<Russian>Вкл. подбор прикрепленных гранат</Russian>
<Japanese>取り付けられた投てき物の拾い上げを有効化</Japanese>
<Japanese>装着済の投擲物の拾い上げを有効化</Japanese>
<Polish>Zezwól na podnoszenie przyczepionych obiektów miotanych</Polish>
<German>Aktiviere erneute Aufnahme befestigter Wurfobjekte</German>
<Korean>부착 투척물 줍기 활성화</Korean>
<French>Activer le ramassage d'objets lançables attachés</French>
<Italian>Abilita Raccogli Oggetti Lanciabili da altri Oggetti</Italian>
<Italian>Abilita Raccolta Lanciabili Attaccati</Italian>
<Chinese>啟用可撿取附著投擲物</Chinese>
<Chinesesimp>启用捡取附着投掷物</Chinesesimp>
<Portuguese>Permitir pegar arremessáveis fixados</Portuguese>
@ -174,27 +174,47 @@
<English>Enables ability to pick up throwables from attached objects.</English>
<Spanish>Activa la habilidad de lanzar objetos enganchados</Spanish>
<Russian>Включает возможность подбирать гранаты, прикрепленные к объектам.</Russian>
<Japanese>取り付けられた投てき物を拾い上げる機能を有効化します。</Japanese>
<Japanese>オブジェクトに装着された投擲物を拾う機能を有効化します。</Japanese>
<Polish>Umożliwia podnoszenie obiektów miotanych przyczepionych do innych obiektów.</Polish>
<German>Aktiviert die Möglichkeit, befestigte Wurfobjekte erneut aufzunehmen.</German>
<Korean>부착된 투척물을 주울 수 있게 해줍니다.</Korean>
<French>Active la possibilité de ramasser des objets lançables attachés à d'autres objets.</French>
<Italian>Abilita la possibilità di raccogliere gli oggetti lanciabili dagli altri oggetti. </Italian>
<Italian>Permette ai giocatori di raccogliere gli oggetti lanciabili da altri oggetti attaccati.</Italian>
<Chinese>啟用後, 可撿取附著在物件上的投擲物</Chinese>
<Chinesesimp>启用后,可捡取附着在物体上的投掷物</Chinesesimp>
<Portuguese>Permite que arremessáveis fixados em objetos sejam pegos.</Portuguese>
<Czech>Zapíná schopnost zvednutí předmětů z objektů ke kterým jsou připnuté.</Czech>
</Key>
<Key ID="STR_ACE_Advanced_Throwing_EnableTempWindInfo_DisplayName">
<English>Show Temporary Wind Info</English>
<German>Zeige temporäre Windinformationen</German>
<Italian>Mostra informazioni sul vento temporaneamente</Italian>
<Japanese>一時的に風の情報を表示</Japanese>
<Korean>바람 정보 임시로 표시</Korean>
<French>Afficher temporairement les informations sur le vent</French>
<Russian>Временно показать информацию о ветре</Russian>
<Spanish>Mostrar información del viento temporalmente</Spanish>
</Key>
<Key ID="STR_ACE_Advanced_Throwing_EnableTempWindInfo_Description">
<English>Temporarily display Wind Info while throwing, to aid in placing smoke grenades effectively.</English>
<German>Zeige während des werfens Windinformationen an, um Rauchgranaten effektiver zu platzieren.</German>
<Italian>Mostra le informazioni sul vento durante il lancio di granate, facilitando il piazzamento ottimale di fumogeni.</Italian>
<Japanese>投擲行動中に風向きの情報を一時的に表示し、発煙手榴弾の煙幕を効果的に展開しやすくします。</Japanese>
<Korean>연막탄을 효과적으로 배치하는 데 도움이 되도록 투척하는 동안 일시적으로 바람 정보를 표시합니다.</Korean>
<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 ID="STR_ACE_Advanced_Throwing_Prepare">
<English>Prepare/Change Throwable</English>
<Spanish>Preparar/Cambiar objetos lanzables</Spanish>
<Russian>Подготовить/заменить гранату</Russian>
<Japanese>投てき物の準備/変更</Japanese>
<Japanese>物の準備/変更</Japanese>
<Polish>Przygotuj/zmień ob. miotany</Polish>
<German>Wurfobjekt vorbereiten/wechseln</German>
<Korean>투척물 준비/변경</Korean>
<French>Préparer/Changer d'objet lançable</French>
<Italian>Prepara/Cambia Oggetto lanciabile</Italian>
<Italian>Prepara/Cambia Oggetto Lanciabile</Italian>
<Chinese>準備/變更投擲物</Chinese>
<Chinesesimp>准备/变更投掷物</Chinesesimp>
<Portuguese>Preparar/Mudar Arremessável</Portuguese>
@ -204,12 +224,12 @@
<English>Throwable Drop Mode (Hold)</English>
<Spanish>Modo soltar objeto lanzable (Mantener pulsado)</Spanish>
<Russian>Режим броска гранаты (удерживать)</Russian>
<Japanese>てきモード (押している間)</Japanese>
<Japanese>モード (押している間)</Japanese>
<Polish>Tryb upuszczania ob. miotanego (przytrzymaj)</Polish>
<German>Wurfobjekt Fallmodus (halten)</German>
<Korean>투척물 떨어뜨리기 모드(꾹눌러서)</Korean>
<French>Mode de lancé de l'objet (Tenir)</French>
<Italian>Modalità Oggetto Gettabile (Mantenere)</Italian>
<Italian>Modalità Gettare (Tieni premuto)</Italian>
<Chinese>投擲模式 (按住)</Chinese>
<Chinesesimp>投掷模式(按住)</Chinesesimp>
<Portuguese>Modo de Arremesso (Segurar)</Portuguese>
@ -219,12 +239,12 @@
<English>Throwable Drop Mode (Toggle)</English>
<Spanish>Modo soltar objeto lanzable (interruptor)</Spanish>
<Russian>Режим броска гранаты (переключить)</Russian>
<Japanese>てきモード (切り替え)</Japanese>
<Japanese>モード (切り替え)</Japanese>
<Polish>Tryb upuszczania ob. miotanego (przełącz)</Polish>
<German>Wurfobjekt Fallmodus (umschalten)</German>
<Korean>투척물 떨어뜨리기 모드(토글)</Korean>
<French>Mode de lancé de l'objet (Basculer)</French>
<Italian>Modalità Oggetto lanciabile Gettabile (Interruttore)</Italian>
<Italian>Modalità Getta Oggetto (Cambia)</Italian>
<Chinese>投擲模式 (切換)</Chinese>
<Chinesesimp>投掷模式(切换)</Chinesesimp>
<Portuguese>Modo de Arremesso (Alternar)</Portuguese>
@ -234,12 +254,12 @@
<English>Primed</English>
<Spanish>Preparado</Spanish>
<Russian>Подготовлена</Russian>
<Japanese>点火</Japanese>
<Japanese>点火した</Japanese>
<Polish>Odbezpieczony</Polish>
<German>Scharf gemacht</German>
<Korean>뇌관 작동</Korean>
<French>amorcée</French>
<Italian>Armato</Italian>
<Italian>Innescato</Italian>
<Chinese>引信開始燃燒</Chinese>
<Chinesesimp>已开引信</Chinesesimp>
<Portuguese>Preparado</Portuguese>
@ -254,7 +274,7 @@
<German>Werfen</German>
<Korean>던지기</Korean>
<French>Lancer</French>
<Italian>Lanciare</Italian>
<Italian>Lancia</Italian>
<Chinese>投擲</Chinese>
<Chinesesimp>投掷</Chinesesimp>
<Portuguese>Arremessar</Portuguese>
@ -270,7 +290,7 @@
<German>(Scrollen) Modus wechseln</German>
<Korean>(마우스 휠) 모드 변경</Korean>
<French>(Défilement) Changer de mode</French>
<Italian>(Scorrere) Cambio Modalità</Italian>
<Italian>(Scorri) Cambia Modalità</Italian>
<Chinese>(滾輪) 變更模式</Chinese>
<Chinesesimp>(滚轮)变更模式</Chinesesimp>
<Portuguese>(Roda do Mouse) Alternar modo</Portuguese>
@ -286,10 +306,10 @@
<German>(Scrollen) Erweitern</German>
<Korean>(마우스 휠) 연장</Korean>
<French>(Défilement) Étendre</French>
<Italian>(Scorrere) Estendere</Italian>
<Italian>(Scorri) Estendi</Italian>
<Chinese>(滾輪) 延長</Chinese>
<Chinesesimp>(滚轮)延长</Chinesesimp>
<Portuguese>(Roda do Mouse) Extender</Portuguese>
<Portuguese>(Roda do Mouse) Estender</Portuguese>
<Czech>(Scrollovat) Oddálit</Czech>
<Turkish>(Tekerlek) Uzat</Turkish>
</Key>
@ -302,7 +322,7 @@
<German>(Klicken) Abkochen</German>
<Korean>(클릭) 예열</Korean>
<French>(Clique) Dégoupiller</French>
<Italian>(Click) Arma</Italian>
<Italian>(Click) Innesca</Italian>
<Chinese>(點擊) 提早拉開引信</Chinese>
<Chinesesimp>(点击)提早拉开引信</Chinesesimp>
<Portuguese>(Clique) Cozinhar</Portuguese>
@ -313,7 +333,7 @@
<English>Pick Up</English>
<Spanish>Coger</Spanish>
<Russian>Подобрать</Russian>
<Japanese>い上げる</Japanese>
<Japanese></Japanese>
<Polish>Podnieś</Polish>
<German>Aufheben</German>
<Korean>줍기</Korean>

View File

@ -1,3 +1,5 @@
PREP(assignNVG);
PREP(assignNVGpfh);
PREP(drawCuratorGarrisonPathing);
PREP(garrison);
PREP(garrisonMove);

View File

@ -16,7 +16,7 @@
} forEach _sections;
}] call CBA_fnc_addEventHandler;
[QGVAR(unGarrison), FUNC(unGarrison)] call CBA_fnc_addEventHandler;
[QGVAR(unGarrison), LINKFUNC(unGarrison)] call CBA_fnc_addEventHandler;
[QGVAR(doMove), {
params ["_unitsArray"];
@ -68,3 +68,11 @@
params ["_unit", "_mode"];
_unit enableGunLights _mode;
}] call CBA_fnc_addEventHandler;
if (isServer) then {
["CAManBase", "init", {
// wait for HMD to be assigned so `hmd _unit` works
[LINKFUNC(assignNVG), _this, 1] call CBA_fnc_waitAndExecute;
}] call CBA_fnc_addClassEventHandler;
};

View File

@ -6,4 +6,11 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
if (isServer) then {
GVAR(assignNVGthread) = false;
GVAR(assignNVGstate) = false;
};
#include "initSettings.inc.sqf"
ADDON = true;

View File

@ -0,0 +1,39 @@
#include "..\script_component.hpp"
/*
* Author: Jonpas
* Assigns AI first found NVG in their inventory during night time and unassigns it during day time.
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [cursorObject] call ace_ai_fnc_assignNVG
*
* Public: No
*/
if (!GVAR(assignNVG)) exitWith {};
params ["_unit"];
if (alive _unit && {!isPlayer _unit}) then {
private _nvg = hmd _unit;
if (GVAR(assignNVGstate)) then {
if (_nvg == "") then {
private _items = [_unit, false, true, true, true, false, false] call CBA_fnc_uniqueUnitItems; // backpack, vest, uniform
{
if (getText (configFile >> "CfgWeapons" >> _x >> "simulation") == "NVGoggles") exitWith {
_unit assignItem _x;
};
} forEach _items;
};
} else {
if (_nvg != "" && {currentVisionMode _unit == 0} && {_unit canAdd _nvg}) then {
_unit unassignItem _nvg;
};
};
};

View File

@ -0,0 +1,27 @@
#include "..\script_component.hpp"
/*
* Author: Jonpas
* waitAndExecute Handler for periodic NVG assignment.
*
* Arguments:
* None
* Return Value:
* None
*
* Example:
* [] call ace_ai_fnc_assignNVGpfh
*
* Public: No
*/
TRACE_1("assignNVGpfh",count allUnits);
if (!GVAR(assignNVG)) exitWith { TRACE_1("shutdown loop",_this); GVAR(assignNVGthread) = false; };
GVAR(assignNVGstate) = sunOrMoon < 1 || {moonIntensity > 0.8};
{
_x call FUNC(assignNVG);
} forEach allUnits;
[FUNC(assignNVGpfh), [], 300] call CBA_fnc_waitAndExecute;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: alganthe
* Draws AI garrison pathing while the Zeus display is open.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: alganthe
* Garrison function used to garrison AI inside buildings.
@ -7,8 +7,8 @@
* 0: The building(s) nearest this position are used <POSITION>
* 1: Limit the building search to those type of building <ARRAY>
* 2: Units that will be garrisoned <ARRAY>
* 3: Radius to fill building(s) <SCALAR> (default: 50)
* 4: 0: even filling, 1: building by building, 2: random filling <SCALAR> (default: 0)
* 3: Radius to fill building(s) <NUMBER> (default: 50)
* 4: 0: even filling, 1: building by building, 2: random filling <NUMBER> (default: 0)
* 5: True to fill building(s) from top to bottom <BOOL> (default: false) (note: only works with filling mode 0 and 1)
* 6: Teleport units <BOOL> (default: false)
@ -33,7 +33,7 @@ if (_startingPos isEqualTo [0,0,0]) exitWith {
[LSTRING(GarrisonInvalidPosition)] call EFUNC(common,displayTextStructured);
};
if (count _unitsArray == 0 || {isNull (_unitsArray select 0)}) exitWith {
if (_unitsArray isEqualTo [] || {isNull (_unitsArray select 0)}) exitWith {
TRACE_1("fnc_garrison: Units error",_unitsArray);
[LSTRING(GarrisonNoUnits)] call EFUNC(common,displayTextStructured);
};
@ -43,7 +43,7 @@ if (_fillingRadius >= 50) then {
_buildings = [_buildings] call CBA_fnc_shuffle;
};
if (count _buildings == 0) exitWith {
if (_buildings isEqualTo []) exitWith {
TRACE_1("fnc_garrison: Building error",_buildings);
[LSTRING(GarrisonNoBuilding)] call EFUNC(common,displayTextStructured);
};
@ -128,7 +128,7 @@ switch (_fillingType) do {
} else {
private _pos = _building select 0;
private _nearestUnits = (_pos nearEntities ["CAManBase", 2]);
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits, {floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits,{floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
if (count _nearestUnits > 0 && {[_nearestUnits, _pos] call _fnc_comparePos}) then {
LOG(format [ARR_2("fnc_garrison: Unit present | removing position | %1 positions remaining for this building",count (_buildingsIndex select (_buildingsIndex find _building)) - 1)]);
@ -177,7 +177,7 @@ switch (_fillingType) do {
} else {
private _pos = _building select 0;
private _nearestUnits = (_pos nearEntities ["CAManBase", 2]);
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits, {floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits,{floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
if (count _nearestUnits > 0 && {[_nearestUnits, _pos] call _fnc_comparePos}) then {
LOG(format [ARR_2("fnc_garrison: Unit present | removing position | %1 positions remaining for this building",count (_buildingsIndex select (_buildingsIndex find _building)) - 1)]);
@ -224,7 +224,7 @@ switch (_fillingType) do {
} else {
private _pos = selectRandom _building;
private _nearestUnits = (_pos nearEntities ["CAManBase", 2]);
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits, {floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits,{floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
if (count _nearestUnits > 0 && {[_nearestUnits, _pos] call _fnc_comparePos}) then {
LOG(format [ARR_2("fnc_garrison: Unit present | removing position | %1 positions remaining for this building",count (_buildingsIndex select (_buildingsIndex find _building)) - 1)]);
@ -258,7 +258,7 @@ switch (_fillingType) do {
};
};
TRACE_1(format [ARR_2("fnc_garrison: while loop ended | %1 units ready to be treated by PFH",count _unitMoveList)], _teleport);
TRACE_1(format [ARR_2("fnc_garrison: while loop ended | %1 units ready to be treated by PFH",count _unitMoveList)],_teleport);
// Update the unit list and remove duplicate positions and units
private _garrison_unitMoveList = missionNameSpace getVariable [QGVAR(garrison_unitMoveList), []];
@ -279,5 +279,5 @@ if (_teleport) then {
[_unitMoveList] call FUNC(garrisonMove);
};
TRACE_1(format [ARR_3("fnc_garrison: End | %1 units left | %2 buildings left", count _unitsArray, count _buildingsIndex)], _unitsArray);
TRACE_1(format [ARR_3("fnc_garrison: End | %1 units left | %2 buildings left",count _unitsArray,count _buildingsIndex)],_unitsArray);
_unitsArray

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: alganthe
* Internal function used by ace_ai_fnc_garrison to make the units move to the positions it picked.
@ -81,13 +81,13 @@ if (isNil QGVAR(garrison_moveUnitPFH)) then {
[QGVAR(enableAttack), [[_unit], true], _unit] call CBA_fnc_targetEvent;
};
LOG(format [ARR_2("garrisonMove PFH: unit in position | %1 units left", count _unitMoveList)]);
LOG(format [ARR_2("garrisonMove PFH: unit in position | %1 units left",count _unitMoveList)]);
};
// Check if unit is alive or even existing
if (!alive _unit || {_unit getVariable [QGVAR(garrisoned), false]}) then {
_unitMoveList deleteAt (_unitMoveList find _x);
LOG(format [ARR_2("garrisonMove PFH: unit dead, deleted or garrisoned via TP | %1 units left", count _unitMoveList)]);
LOG(format [ARR_2("garrisonMove PFH: unit dead, deleted or garrisoned via TP | %1 units left",count _unitMoveList)]);
} else {
private _unitPos = getPos _unit;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: mharis001
* Initializes the Zeus display.

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: alganthe
* Used to un-garrison units.
@ -28,7 +28,7 @@ _units = _units select {local _x};
private _leader = leader _unit;
TRACE_3("fnc_ungarrison: unit and leader",_unit , _leader, (_leader == _unit));
TRACE_3("fnc_ungarrison: unit and leader",_unit,_leader,(_leader == _unit));
_unit setVariable [QGVAR(garrisonned), false, true];

View File

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

View File

@ -0,0 +1,19 @@
private _category = format ["ACE %1", LLSTRING(DisplayName)];
[
QGVAR(assignNVG), "CHECKBOX",
[LSTRING(AssignNVG_DisplayName), LSTRING(AssignNVG_Description)],
_category,
false,
1,
{
if (isServer) then {
params ["_enabled"];
if (_enabled && {!GVAR(assignNVGthread)}) then {
TRACE_1("start loop",_this);
GVAR(assignNVGthread) = true;
[FUNC(assignNVGpfh), [], 1] call CBA_fnc_waitAndExecute;
};
};
}
] call CBA_fnc_addSetting;

View File

@ -1,6 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="AI">
<Key ID="STR_ACE_AI_DisplayName">
<English>AI</English>
<Chinese>AI</Chinese>
<French>IA</French>
<Spanish>IA</Spanish>
<Italian>IA</Italian>
<Polish>SI</Polish>
<Russian>ИИ</Russian>
<German>KI</German>
<Czech>UI</Czech>
<Portuguese>IA</Portuguese>
<Korean>AI</Korean>
<Chinesesimp>AI</Chinesesimp>
<Japanese>AI</Japanese>
<Turkish>AI</Turkish>
</Key>
<Key ID="STR_ACE_AI_GarrisonInvalidPosition">
<English>Invalid position provided.</English>
<German>Ungültige Position</German>
@ -65,5 +81,29 @@
<Czech>Nenalezena žádná budova.</Czech>
<Turkish>Bir yapı bulunamadı</Turkish>
</Key>
<Key ID="STR_ACE_AI_AssignNVG_DisplayName">
<English>Auto-Equip NVGs</English>
<Polish>Automatyczne zakładanie NVG</Polish>
<German>Automatisch NVGs ausrüsten</German>
<Italian>Equipaggia NVG in automatico</Italian>
<Korean>야투경 자동 창착</Korean>
<French>Equipement JVN automatique</French>
<Portuguese>Equipar NVGs automaticamente</Portuguese>
<Japanese>暗視装置の自動装備</Japanese>
<Russian>Автоматическое оснащение ПНВ</Russian>
<Spanish>Auto equipar gafas de visión nocturna</Spanish>
</Key>
<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>
<Polish>Zakłada NVG w nocy i zdejmuje je w ciągu dnia.\nNie dodaje NVG do ekwipunku!</Polish>
<German>Rüstet NVG nachts aus dem Inventar aus und entfernt es tagsüber.\nFügt keine NVGs zum Inventar hinzu!</German>
<Italian>Equipaggia NVG dall'inventario durante la notte, e li mette nell'inventario durante il giorno.\nNon aggiunge NVG all'inventario se non sono presenti.</Italian>
<Korean>야간에는 야투경을 소지품에 장착하고 주간에는 장착을 해제합니다.\n주의! 소지품에 야투경을 추가하는 것이 아닙니다!</Korean>
<French>Equipe des JVN pendant la nuit et les déséquipe le jour.\nN'ajoute pas les JVN dans l'intenvaire !</French>
<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>
<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>
</Package>
</Project>

View File

@ -12,6 +12,6 @@ class Extended_PreInit_EventHandlers {
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_postInit));
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
};
};

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: Dystopian
* Check if Eject action can be shown.
@ -30,6 +30,6 @@ _vehicle == vehicle _unit
if (_unit == _x select FULLCREW_UNIT) exitWith {
_ejectVarName = format [QGVAR(ejectAction_%1_%2), _x select FULLCREW_ROLE, _x select FULLCREW_TURRETPATH];
};
} count fullCrew _vehicle;
} forEach fullCrew _vehicle;
_vehicle getVariable [_ejectVarName, false]
}

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Adds actions to a drone
@ -22,7 +22,7 @@ if (!alive _vehicle) exitWith {};
if (_vehicle getVariable [QGVAR(droneActionsAdded), false]) exitWith {};
_vehicle setVariable [QGVAR(droneActionsAdded), true];
// move to location
// Move to location
private _condition = {
params ["_vehicle"];
(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);
[_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 {
// loiter at location
// Loiter at location
_condition = {
params ["_vehicle"];
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
};
_statement = {
_statement = {
params ["_vehicle"];
private _group = group driver _vehicle;
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);
// set height
// Set height
_condition = {
params ["_vehicle"];
(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];
// set loiter radius
// Set loiter radius
_condition = {
params ["_vehicle"];
private _group = group driver _vehicle;
@ -97,7 +146,7 @@ if (_vehicle isKindOf "Air") then {
} forEach [500, 750, 1000, 1250, 1500];
// set loiter direction
// Set loiter direction
_condition = {
params ["_vehicle", "", "_args"];
private _group = group driver _vehicle;

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Get drone's target location, if aimed at infinity it will return a virtual point

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Modify the current waypoint of a drone
@ -17,13 +17,13 @@
*
* Public: No
*/
params ["_vehicle", "_group", "_type", "_value"];
TRACE_4("droneModifyWaypoint",_vehicle,_group,_type,_value);
private _index = (currentWaypoint _group) min count waypoints _group;
private _waypoint = [_group, _index];
switch (toLower _type) do {
switch (toLowerANSI _type) do {
case ("height"): {
private _pos = waypointPosition _waypoint;
_pos set [2, _value];

View File

@ -1,4 +1,4 @@
#include "script_component.hpp"
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Set new waypoint of a drone
@ -8,6 +8,7 @@
* 1: Group <GROUP>
* 2: Pos 2D <ARRAY>
* 3: Type <STRING>
* 4: Target to follow <OBJECT> (default: objNull)
*
* Return Value:
* None
@ -18,7 +19,7 @@
* Public: No
*/
params ["_vehicle", "_group", "_pos", "_type"];
params ["_vehicle", "_group", "_pos", "_type", ["_target", objNull]];
TRACE_4("droneSetWaypoint",_vehicle,_group,_pos,_type);
private _index = (currentWaypoint _group) min count waypoints _group;
@ -29,11 +30,39 @@ private _currentLoiterRadius = waypointLoiterRadius _waypoint;
private _currentLoiterType = waypointLoiterType _waypoint;
// Set pos to ATL
_pos set [2, if (_currentHeight >= 50) then { _currentHeight } else { 0 }];
_pos set [
2,
[0, _currentHeight] select (_currentHeight >= 50)
];
// [_group] call CBA_fnc_clearWaypoints;
_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);
if (_currentHeight > 1) then { _vehicle flyInHeight _currentHeight; };

Some files were not shown because too many files have changed in this diff Show More